Do people buy paper vs ebooks

Scott and my certification books have always sold way more paper copies than e-books. While I personally like paper books better, I got the sense that they were less popular in general.

Recently I was asked by someone who wanted to buy Real World Java if he should buy the paper or e-book. I advised paper because

  • Easier to read code
  • Higher quality (I’ve seem some errors in the Kindle that are not in the manuscript we have Amazon)
  • I can sign it.

Plus you can pass around a paper book. The person who asked me listed a benefit of being able to read the Kindle on the train. I find paper books easier to read on the train. While I’m fine with being on my phone, I’m not going to sit there with a tablet out. So the extra weight of a book is worth it. Plus I can write it in it (if it is my book and not a library book)

Anyway, I thought it would be fun to look at actual sales numbers for my most recent books. Note that Safari numbers are not included in here. For Safari we get a license fee but I don’t know how many people actually read it.

TitlePercentage of paper books out of total
Real World Java98%
OCP Java 21 Developer Study Guide87%
OCP Java 17 Developer Study Guide94%
Java 17 Practice Tests89%

2025 attempt to buy us open tickets

Last year was the first year it was hard to buy US Open tickets. In 2023 and earlier, I would buy them after work during the American Presale, no problem. Ok fine, it’s going to be like Comic-Con where you have to buy them the second they become available. Here’s how that went.

Tuesday – American Express Presale

Sales start at 9am. I was on the site before that. Everyone on the site gets a random number. Mine was 3200. The number went down slowly to about 2200 (over about 40 minutes) and then flew down to zero. When I got in, I was able to see Grounds Passes for the day I wanted. I attempted to put it in my cart and it said they were no longer available. I repeated this a few times and then it stopped saying available at all.

I then went to buy my Ashe ticket for a different day. I made the mistake of using a different browser tab so back in the queue. (You can’t use multiple devices or multiple tabs.) It took less time to get to the front of the queue this time and I was a able to get a ticket. A big change this year is they just tell you the row number and not the seat number. Which is annoying because I want to be within a few seats of the aisle and not some random place in the row. After I paid, I got my actual seat number which turns out to be an aisle.

I paid with my american express card and was not prompted for a one time pass code texted to my cell. (This is important; remember this)

Friday – Public sale

I know they don’t release all the tickets during the presale so I tried again. I was on the Ticketmaster site before 9am. This time, I got number 19 in queue. Awesome. There were plenty of grounds passes for the day I wanted. (And plenty of resellers charging double price.) I put three official tickets in my card for myself and my friends. Great. I didn’t get that far on Tuesday.

I then went to pay. Where I get prompted for a one time PIN that “was texted to me.” It was not. I tried clicking resend a few times. No text. Unfortunately I didn’t have another credit card with me. Then my session timed out. I tried again (at 9:15am) and all the non-resale grounds passes were gone.

The future

The US Open did release more grounds passes closer to the time last year. But you have to keep checking to see when which is annoying. Also last year, they didn’t sell grounds passes in person. You have to buy them online.

switching the coderanch build to gitlab

After having some “trouble” upgrading Jenkins on the CodeRanch server, we concluded it would be easier to switch to GitLab for the build than fix it. After all, we are already using GitLab SaaS (software as a service) for source control. While I’ve done GitLab pipelines before, this was my first time using Ant in one so it was interesting. Which means a blog post.

Why we use Ant and our custom deployment model

We have a few CodeRanch moderators who work on the forum software. (Less than 5 which is convenient as that’s how many people can be in a GitLab org for free. One of those moderators lives in a country with less than reliable internet. This means using Maven (or even Ant with Ivy) is a problem because it expects more internet than he may have available at a given moment.

Additionally, uploading large files is sometimes a problem so we don’t deploy a .war file. We instead deploy a loosefiles.zip file which contains the code but not all the dependencies. The dependencies are uploaded only on change.

I don’t recommend any company operate like this but it meets our needs. And since it is a hobby, also gives us fun technical challenges.

Fun fact: when I started working on the forum software (17 years ago) I had dialup internet. It was reliable, but I also benefited from the no uploading a war file sized artifact personally.

The main build part of the pipeline

Ant isn’t supported for Auto DevOps so didn’t consider that approach. The main part of the build was fairly straightforward:

image: eclipse-temurin:21

variables:
  FF_TIMESTAMPS: 1

ant-dist:
  stage: build
  before_script:
    - apt-get update && apt-get install -y ant
  script:
    - ant dist
  artifacts:
    paths:
      - qa/
      - dist/
    reports:
      junit: qa/reports/*.xml
    expire_in: 1 week
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_COMMIT_BRANCH == "master"'

The pipeline uses a Java 21 image (last LTS as of when set up). I added FF_TIMESTAMPS so the log output tells me how long everything takes. (The free plan gives you a certain number of build minutes per month so this is important. Using this information we decided not to have the build create the deployment artifact (which minifies files and zips them up) as that took a bunch of time and the people who deploy always run that locally anyway.

The apt-get takes about 15 seconds to install Ant (I checked this because I would have included Ant in the repo if it was slow). Next comes actually running the dist target of the build which compiles, runs the JUnit tests and PMD for static analysis.

Next the pipeline makes the qa (build reports) and dist (binaries) available for browsing/downloading. It also publishes the JUnit output which allows the merge request and pipeline to conveniently show test data.

Finally, the triggers are merge requests and master..

Setting up semgrep

Since SAST is free on GitLab I set that up as well. The remainder of the pipeline is

# based on https://semgrep.dev/docs/semgrep-ci/sample-ci-configs#sample-gitlab-cicd-configuration-snippet
semgrep:
  # A Docker image with Semgrep installed.
  image: semgrep/semgrep
  # Run the "semgrep scan" command on the command line of the docker image.
  script: semgrep ci --config auto --include src --gitlab-sast --output=gl-sast-report.json --text-output=semgrep.txt --json-output=semgrep.json --sarif-output=semgrep.sarif || true
 
  variables:
    # Upload findings to GitLab SAST Dashboard:
    SEMGREP_GITLAB_JSON: "1"
 
  artifacts:
    paths:
        - semgrep.txt
        - semgrep.json
        - semgrep.sarif
    reports:
      sast: gl-sast-report.json
    expire_in: 1 week

  rules:
  # Scan changed files in MRs, (diff-aware scanning):
  - if: $CI_MERGE_REQUEST_IID

  # Scan mainline (default) branches and report all findings.
  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  

While most of this code came from the sample, semgrep was far more interesting. You can publish to semgrep.dev and see the results in a nice UI. It says that is free for up to 10 committers. Cool we have less than that. However, when the project comes from GitLab, it requires a GitLab group token with admin access. I was less enthusiastic about that. But even then, I still couldn’t use it because GitLab free product doesn’t allow you to set up group access tokens.

You might be wondering why there are so many output formats. Free GitLab basically tells you if there are new findings, but not a visual display of the full report. And I’m not sure what the other developers will want to use so I provided everything. I plan to use SARIF. There are two free visualizers: