Get in Touch
About Us Insights Newsroom Gallery Why AtomicNorth Get in Touch

Java that outlives
the team that wrote it

Enterprise Java and JVM development: Spring services, APIs, batch, and the migrations that get a working system off an application server nobody wants to touch.

Nothing is refactored before there is a test that proves the old behaviour, because on a system this old the specification is the code.

StackJava, Spring, Kotlin

Spring Boot and Spring Framework, with Kotlin on the JVM where the team already reads it.

ScopeBuild and maintain

The same engineers who ship the first release are the ones answering for it afterwards.

MigrationsRuntimes and versions

Off legacy application servers, and off Java versions that no longer receive security updates.

HandoverDocumented as built

Architecture notes, build instructions and run books written during the work, not reconstructed at the end.

What we build

Enterprise Java, written to be maintained

Java earns its place in systems that have to keep running for a decade. That is also why most Java work is inherited rather than started, and why the first skill required is reading somebody else's code honestly.

Spring services and APIs

Spring Boot services, REST and messaging interfaces, authentication and authorisation, and the contracts between them written down before the code.

Interfaces are versioned from the first release. Retrofitting versioning onto an API with live consumers is the expensive kind of avoidable work.

Services a second team can call without asking questions.

Application server migration

Moving applications off WebLogic, WebSphere and older JBoss onto Spring Boot with an embedded container, including the vendor-specific code that made them portable in theory only.

JNDI lookups, container-managed transactions, proprietary deployment descriptors and the classloader tricks are dealt with individually rather than swept into a rewrite.

One less licensed runtime under the application.

Java version upgrades

Moving from Java 8 or 11 onto a supported release: module system consequences, removed internal APIs, changed defaults, and the dependency tree that resists all of it.

Upgrades run incrementally with the suite green at each step, because a single jump on a large codebase leaves you unable to tell which change broke what.

A runtime that still receives security updates.

Integration and messaging

Kafka, JMS and file-based interfaces to the systems around the application, including Oracle and Microsoft estates we already support elsewhere.

Consumers are idempotent and replayable. A message delivered twice should be dull, and on most inherited systems it is not.

Interfaces that fail loudly and recover without a manual fix.

Persistence and performance

JPA and Hibernate mappings, query behaviour, connection pooling, caching, and the N plus one problems that only appear with real data volumes.

Performance work starts with measurement against production-shaped data. Tuning against a small test database produces confident nonsense.

Query behaviour you can explain, not just observe.

Taking over an inherited codebase

Build restored, dependencies inventoried, a test harness put around the critical paths, and the undocumented behaviour written down as it is found.

The first deliverable is usually a repeatable build on a clean machine, which more inherited Java projects lack than anyone expects.

A codebase a new engineer can change without fear.

How a Java engagement runs

StepOneRead

The code, the build, the runtime configuration and the data model, alongside the people who know why an odd decision was made.

Reading comes before opinions. An architecture that looks wrong from outside is often the residue of a constraint that still exists.

You receive:

An assessment you keep

Component map, dependency and version position, the parts under test and the parts not, and the risks ranked by what they cost when they fail.

Written for your engineers rather than as a sales document, and yours whatever happens next.

StepTwoCover

Tests around the behaviour that must not change: the critical paths, the batch outputs, the interface contracts and the awkward edge cases.

This is the step clients ask to skip. It is the step that decides whether the later work is a migration or a gamble.

You receive:

A characterisation suite

Automated tests covering the paths agreed as critical, running in a pipeline, with the current behaviour captured as the baseline to compare against.

Where behaviour turns out to be wrong, it is reported rather than quietly corrected during a migration.

StepThreeChange

The build modernised, the runtime moved, the Java version raised, and the code changed in slices that each leave the suite green.

Slices go to a real environment as they land. A migration held in a branch for months is not progress, it is deferred merging.

You receive:

Working software in stages

Each slice deployed, exercised against converted data, and reversible. No go-live date is fixed until a full rehearsal runs clean.

The cutover has a written rollback path with the decision points named.

StepFourRun

Steady state: defect handling, dependency and security updates, capacity review, and the small changes the business keeps needing.

Long-lived systems decay through neglected dependencies more often than through new features. That maintenance is scheduled, not requested.

You receive:

A support cadence

Dependency and vulnerability position stated on a cycle, change log, defect trends, and the plan for anything deferred with an owner against it.

Documentation updated with each change rather than as a separate project nobody funds.

01
Coverage

What sits in the Java practice

Delivered as a project, as a maintenance retainer, or as a project that converts into a retainer once the first release is live.

Java Development coverage
AreaTechnologyScopeModel
Services and APIs Spring Boot, Spring Framework, KotlinDesign, build, contract versioning, automated testingProject or retainer
Runtime migration WebLogic, WebSphere, JBoss, TomcatAssessment, container migration, vendor code removal, rehearsalProject
Version upgrades Java 8 and 11 onto supported releasesDependency remediation, incremental upgrade, regression suiteProject
Integration Kafka, JMS, REST, file interfacesInterface build, idempotency, replay, reconciliationProject or retainer
Persistence JPA, Hibernate, Oracle and SQL ServerMapping review, query tuning, pooling, cachingProject or retainer
Batch Spring Batch, scheduled jobsJob design, restartability, failure handling, monitoring hooksProject or retainer
Maintenance Existing Java codebasesDefect handling, dependency updates, small change deliveryRetainer
Upgrades

An unsupported runtime is a security decision

Running an old Java version rarely feels urgent. The application works, nothing has broken, and the upgrade competes with features for the same budget. The exposure builds quietly: no security patches, libraries that no longer publish fixes for that baseline, and a shrinking pool of engineers willing to work on it.

The way through is incremental rather than heroic. Get a repeatable build, get tests around the paths that matter, then raise the version in steps with the suite green at each one. Slow, unexciting, and the only approach that lets you stop halfway without damage.

Ask for a Java assessment
  • Position statedJava version, framework versions and known vulnerabilities per component, with the ones that have no available fix named plainly.
  • Upgraded in stepsOne version boundary at a time, each landing in a real environment with the regression suite passing before the next begins.
  • ReversibleEvery step deployed behind a documented rollback, so an upgrade programme can pause without leaving the estate half-migrated.

Indicative practice. Sequencing is set per component after the assessment.

Questions we get asked

Before committing to Java work

Should we rewrite or modernise what we have?

Modernise, in almost every case we see. A rewrite restarts the clock on a decade of accumulated business rules that nobody has written down, and the rewrite is judged against a system that already works. We will argue for a rewrite where the original is genuinely unbuildable or the platform is gone, and we will say so rather than talk you into the larger piece of work.

Nobody here can build the application any more. Is that fatal?

No, and it is common. Restoring a repeatable build on a clean machine is the first task: reconstructing the dependency set, pinning versions, and removing the reliance on one developer's configured laptop. Until that exists nothing else can be verified, so it comes before any change.

Can you work alongside our own Java developers?

Yes, and it usually produces the better outcome. Your team holds the domain knowledge; we bring the migration and testing patterns. The arrangement that fails is split ownership of the same component without a written boundary, so the boundary gets agreed at the start.

Do we have to move off our application server?

Not automatically. If the server is supported, the licence is paid and the application is stable, moving is a cost with no immediate return. The case changes when the platform approaches end of support, when the licence renewal is large, or when the container is the reason nobody can run the application locally. The assessment prices staying as well as moving.

Who owns the code and the documentation?

You do, from the first commit. Repositories sit in your organisation, the build runs on your infrastructure or an account you control, and the architecture notes and run books are yours. Being replaceable is part of the design.

Java thatkeeps running.

Start with a Java assessment. It needs read access to the code and the build rather than a contract, and it produces a ranked risk list you keep either way.

Get in touch Book a scoping call