ORCID-Source: the Java stack behind the ORCID registry
ORCID Open Source Project
At a glance
- What is it?
- ORCID-Source is the code behind the ORCID registry, a set of Java web applications and libraries on Spring Web MVC with PostgreSQL persistence, Jersey REST services and a FreeMarker front end. It is not a library you depend on but a running system you operate, and the interesting parts are its version scheme and its service topology.
- Who is it for?
- Adopt ORCID-Source if you are running an ORCID member registry or a mirror of one, or if you need to understand and operate the service rather than call it. Do not adopt it as a dependency in an application that only needs researcher identifiers, since the API clients listed in POPULAR_CLIENT_LIBRARIES.md are the intended integration path.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
This is the registry itself, not a client library
ORCID-Source is described as the ORCID Open Source Project, and the README opens with a set of links rather than a feature list, because the repository is a pointer to a system rather than a tool you add to a project.
The links cover what is ORCID, an introduction to the ORCID API with a note on content negotiation, the API's XSD including the current stable version, a localization reference, the API user's listserv, the member support center, and a list of popular client libraries.
That last link is the one that tells you what this repository is for. If you are an application developer who needs to attach a researcher identifier to a user account, you use one of the client libraries, and the registry is a service you call over HTTP. ORCID-Source is what you read when you are the other side of that call: running the registry, integrating a member organization, or working on the code itself.
The topics list gives the shape of the thing: Java and JavaScript, Maven, Jenkins, PostgreSQL, and spring-web-mvc. There is no package registry entry, no install command and no API to import. The deliverable is a running deployment.
The licence is reported as Other, a custom licence GitHub cannot classify, with the terms in the LICENSE file and a separate `SHORT_LICENSE.txt` at the root, which is a pattern usually used to publish a summary of a longer, non-standard agreement. The README simply points at LICENSE and at a CREDITS.md file for the contributor list.
The version scheme encodes a rollback boundary
The Versioning section is the most consequential piece of documentation in the repository, and it is short.
The README says the version number used with releases will look to follow a format similar to semver, with the example 1.138.2, and then gives the structure as release that cannot be rolled back, typically database changes, then release sequence, then release patch, with a note in parentheses that the patch counts patches applied after being pushed to production.
So the first number is a one-way door. If that number moves, the release contains a database change, and rolling back means restoring data rather than redeploying the previous build. That is a materially different deployment procedure from reverting a container image, and it is the single fact that most affects how you operate this system.
The patch counter is unusual in the opposite direction. It counts patches applied after the release went to production, which means a production deployment can be ahead of the tagged release. A version you find in a running environment is therefore not necessarily a version you can find in the source tree, and reconstructing what is deployed requires reading the patch history rather than the tag list.
The release history confirms the pace. The listed releases are v3.24.11 on 2026-10-15, v3.24.10 on 2026-10-13 and v3.24.9 on 2026-10-13, so two releases on one day, and the last push was on 2026-10-15 with the repository not archived.
The repository backs this up with a dedicated file. There is a RELEASE.md at the top level alongside HOW_TO_CREATE_NEW_API_VERSION.md, which is where the mechanics of shipping a new API version are described, and a CHANGELOG.md for the running record.
Spring MVC for the web tier, Jersey for the REST services
The General Application Stack section gives the architecture in two paragraphs, and it is worth reading closely because the split between Spring and Jersey is not obvious.
The whole thing is a set of web apps and libraries built in Java with Spring Web MVC, with persistence provided by a Postgres database. On the client side the stack uses HTML, AJAX, JQuery and AngularJS, and server side FreeMarker is used for view rendering.
The backend paragraph refines it. Spring Web MVC is the web framework, Spring Security handles security, the RESTful services are built with Jersey and JAXB, and JPA with Hibernate persists models to the Postgres database.
So there are two HTTP stacks in one system. Spring MVC serves the interactive web application, with FreeMarker templates and an AngularJS front end talking to it over AJAX. Jersey and JAXB serve the public API, which is a different set of endpoints with a different serialization model, and the JAXB part is what makes the XSD referenced from the README meaningful, since JAXB is the Java binding for XML Schema.
The repository layout mirrors that division into modules, and it is extensive. There is `orcid-core`, `orcid-api-web` for the API application, `orcid-internal-api` for the private API, `orcid-api-common` for shared API code, `orcid-persistence` for the data layer, `orcid-web` and `orcid-pub-web-proxy` for the public web tier, `orcid-haprouter` for the routing layer, `orcid-lb` for a load balancer, `orcid-activemq` for messaging, `orcid-message-listener` for consuming that messaging, `orcid-activities-indexer`, and `orcid-nodejs`.
The README is candid that the list above is a brief introduction, that the best way to see everything used is to dig into the code, and that otherwise you should browse the PROJECTS.md page, which exists at the root for exactly that purpose.
Docker Compose profiles separate the database from the app stack
The `docker-compose.yml` at the repository root is the clearest picture of the service topology, and the design decision in it is the use of profiles.
The file defines named services with profiles that decide which subset of the stack comes up. The `redis` service uses the image `orcid/registry/redis:7.2.5-alpine`, exposes port 6379, and belongs to the `db` and `dev` profiles. The `postgres` service uses `postgres:13.13-alpine3.19`, sets the database, user and password environment variables, and mounts the data volume, the init scripts and a config file:
postgres:
image: postgres:13.13-alpine3.19
environment:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
command: postgres -c config_file=/etc/postgresql/postgresql.conf
volumes:
- postgres_data:/var/lib/postgresql/data
- ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
- ./postgres/postgresql.conf:/etc/postgresql/postgresql.conf:roThat Postgres configuration is worth a second look. The `command` line points the server at a config file that is bind-mounted read-only from the repository, so the database configuration is versioned with the code rather than baked into a container layer, and the `docker-entrypoint-initdb.d` mount is the standard hook for seeding a fresh database on first start.
The profile scheme means a developer can bring up only the data layer, only the application, or the full set, without editing the compose file. The `dependencies` service is a special case: it has an entrypoint of `sleep infinity` and belongs to the `build` profile, which is a way to hold a container open as a build target rather than to run anything.
The rest of the file shows the shape of the running system. The `haprouter` service publishes several port mappings including stats, Solr read and write ports and separate Postgres read and write ports, which is the shape of a read replica setup, and the `lb` service publishes 80 and 443 alongside a stats port, which is the load balancer tier.
The Dockerfile copies only poms first, to keep the dependency layer cached
The Dockerfile at the root is a two-stage build with a comment on every line explaining why it is there, and the first stage is about caching rather than about compiling.
It starts from `maven:3.6.3-jdk-11 AS maven`, with a comment noting the version should match the one in `.tool-versions`. It then copies only the `pom.xml` files, one per module, and comments that this is to copy only poms for max cachability of just dependency downloads.
The dependency resolution is done with a flag that expects failures:
RUN mvn -T 1C --batch-mode dependency:resolve --fail-never -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn`--fail-never` with a comment saying it ignores that some components will fail, and `-T 1C` for one thread per core. This is a pragmatic choice for a multi-module build where a single module's unresolved dependency should not stop the whole image from being built.
After that come two Maven `install` invocations, one for the parent POM and one for `orcid-utils`, each with a comment explaining that the builds depend on a version tagged release and therefore need the artifact in the local repository first.
The rest of the file continues the pattern with a series of `COPY` steps for each module's pom and source, and it includes a FIXME comment noting that some modules do not seem required, with their copy lines commented out. That is a small but honest detail: the build script is not fully pruned, and someone left a note saying so.
The build scripts at the root, `build.sh`, `build-wars.sh`, `docker-build.sh`, `deploy.sh` and `entrypoint.sh`, sit alongside a `Jenkinsfile` and a `newrelic.yml` for the APM configuration.
The API is versioned separately from the code, which is the hard part
The most demanding part of running ORCID-Source is not the build, it is the promise that the API does not change under its clients.
The repository makes that explicit with a dedicated file, HOW_TO_CREATE_NEW_API_VERSION.md, and with the API's XSD hosted in a separate repository, the orcid-model project, where the current stable XSD is at the record_2.1 path. The XSD is the contract. A Java service can be refactored freely as long as the XML it emits still validates against that schema.
CONTENT_NEGOTIATION.md at the root handles the other half, since the same endpoint may return XML, JSON or plain text depending on what the client asks for. That is a documented file rather than an emergent behavior, which is the right way to do it.
The consequence for an adopter is a versioning discipline rather than a technical obstacle. An API version bump is a coordinated event: a new XSD, a new record version directory, a deployment, and a deprecation window for the old one. The versioning scheme described in the README, with its first component being a release that cannot be rolled back, typically database changes, exists to make that coordination visible in a version string.
The last piece is the human side. The API user's listserv is where integrators are expected to hear about changes, and the member support center is where member organizations get help. For an organization integrating an ORCID member API, those two channels are as much a part of the adoption decision as the code, because a registry that changes its contract without warning would break every member integration at once.
Editorial conclusion
Adopt ORCID-Source if you are running an ORCID member registry or a mirror of one, or if you need to understand and operate the service rather than call it. Do not adopt it as a dependency in an application that only needs researcher identifiers, since the API clients listed in POPULAR_CLIENT_LIBRARIES.md are the intended integration path. Verify first that the version of the source you pick matches the ORCID API version you must support, because the release numbers encode a database-change boundary that cannot be rolled back.
Frequently asked questions
What is ORCID-Source and who is it for?
It is the open source code of the ORCID registry, a set of web apps and libraries built in Java with Spring Web MVC and Postgres persistence, with Jersey and JAXB for the REST services. It is meant for people running the registry or integrating as a member organization, while application developers are pointed to the popular client libraries instead.
How does ORCID version its releases?
The README says the version follows a format similar to semver, where the first number is a release that cannot be rolled back, typically database changes, the second is the release sequence, and the third counts patches applied after the release was pushed to production. The example given is 1.138.2.
What is the tech stack of the ORCID registry?
The README describes Java web apps and libraries on Spring Web MVC with Spring Security, Jersey and JAXB for the RESTful services, and JPA with Hibernate persisting to a Postgres database. The front end uses HTML, AJAX, JQuery and AngularJS, with FreeMarker for server-side view rendering.
How do I run the ORCID registry locally?
The repository ships a `docker-compose.yml` whose services are grouped into profiles, so a developer can start only the data layer with the `db` profile or the application with `dev`. The postgres service mounts the repository's `docker-entrypoint-initdb.d` directory and its `postgresql.conf`, and the setup details are in DEVSETUP.md.
What licence does ORCID-Source use?
The licence is reported as Other, a custom licence GitHub cannot classify, with the terms in the LICENSE file at the repository root and a shorter summary in SHORT_LICENSE.txt. Contributors are listed in CREDITS.md.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/orcid-orcid-source)Was this useful?