Interview guides · CHAMP Cargosystems
CHAMP Cargosystems Software Engineer Interview Guide
CHAMP Cargosystems Software Engineer interview guide: four reported rounds, Java fundamentals, coding, API design, debugging and a 7-day plan.
The 60-second brief
CHAMP Cargosystems builds software for the air cargo transport chain, used by airlines and freight forwarders. Candidates name two areas for this role: the Cargospot platform and a newer AI Hub. The stack they describe pairs Java systems built on Spring Boot with Python services that add AI features, and the tooling they list includes Docker, OpenShift and GitLab CI. In the role you build and maintain services, add AI and machine-learning features to existing platforms, and take part in code reviews, pair programming and architecture discussions. You also work with product owners to turn business requirements into technical specifications.
This guide is for candidates applying as a Software Engineer, where roughly two to four years of professional development is the typical profile candidates describe. It covers the four reported rounds, the fifteen reported questions (Java fundamentals, coding and design, debugging, and behavioral fit), the architecture topics candidates mention, and a plan for a Java or Python background. It does not cover pay or office-specific terms.
Candidates report four rounds over about 3-5 weeks: HR Screening, Technical Assessments, Meet Engineering Managers and Final Leadership Interviews. The technical stage is described as a mix of live coding, theory exams on Java or Python, and debugging exercises.
Focus areas
- Java
- AI / Artificial Intelligence
- RAG (Retrieval-Augmented Generation)
Overview
The role sits on two kinds of code. One side is long-lived Java services on Spring Boot. The other is newer Python work for the AI Hub, where candidates list generative AI topics such as retrieval-augmented generation (RAG) and prompt engineering as nice-to-have. Pick the language you are strongest in and be ready to go deep there, but be able to say how your code is built, tested and deployed, because Docker, OpenShift and GitLab CI are all on the list.
The reported questions fall into three groups. The Java group is conceptual: interface versus abstract class, how memory and the garbage collector work, the principles of OOP, exceptions in multi-threaded code, and what final, finally and finalize each mean. The coding group is practical: write a pattern-printing program, speed up slow production code, find bugs in a snippet, design an API for a cargo-tracking need, and debug a distributed system. The third group is behavioral. For the open-ended items, the winning move is a repeatable method you can narrate: measure first, state assumptions, name the trade-off.
The later rounds change character. Candidates describe the managers' round as being about team contribution and project management, and the final leadership conversation as being about business impact and overall fit. That means two or three past projects you can explain at architecture level, including what went wrong, what you decided and who you worked with. Candidates also say it helps to learn the basics of the air cargo business, so you can describe your work in terms of airlines, forwarders and shipment data rather than in abstractions. Keep your technical explanations consistent from the first technical conversation to the last.
The CHAMP Cargosystems interview process
Candidates describe four stages, from an HR conversation to leadership interviews, over about 3-5 weeks; another report puts the whole process at one to two weeks, so expect the timing to vary.
HR Screening
Candidates describe this stage as an opening conversation about your background and your interest in the position. Treat it as the place to make your stack and your motivation easy to repeat to the next people in the loop. Your answer to why this company, and a clear summary of your Java or Python experience, will be reused later.
What to demonstrate
- Your background and interest in the position, as candidates describe the stage
- How clearly you connect your experience to the Java/Spring Boot or Python work in the role
- Practical fit such as location and availability
How to prepare
- Write a short CV walkthrough that names your strongest language and any Spring Boot, Docker, GitLab CI or GenAI work, and rehearse it aloud.
- Write your answer to why you want to join CHAMP Cargosystems specifically, using the air cargo domain and the Cargospot and AI Hub areas candidates mention.
- Decide which office or location you could work from, and note questions to ask about the rest of the loop, including whether travel between offices comes up.
Technical Assessments
Candidates describe a series of technical assessments that can include live coding, theoretical exams on Java or Python, and debugging exercises. The reported technical areas are OOP and data structures, API design and testing. The reported questions on Java fundamentals, pattern printing, bug-hunting, slow-code optimization, API design and distributed debugging are the best practice for this stage. Work through the questions that match each format rather than only reading about them.
What to demonstrate
- Working code written live, since the format includes live coding
- Command of Java or Python fundamentals, as the theory exams cover
- Ability to locate and fix defects in code you did not write, as the debugging exercises require
- Experience with unit and integration testing, which candidates list as a technical area
How to prepare
- Write a one-paragraph answer with a short code example for each Java fundamentals question: interface versus abstract class, garbage collection, OOP, multi-threaded exception handling, and final, finally and finalize.
- Code the pattern-printing exercise in your main language until nested loops, string building and edge cases such as a size of zero or one come without hesitation.
- Collect small buggy snippets (off-by-one, null handling, equals without hashCode, unclosed resources, shared mutable state) and practise stating the intent, the defects and a test for each fix.
- Prepare a measure-first method for slow code and a step-by-step method for debugging across services, then say both aloud.
Meet Engineering Managers
Candidates report a discussion with engineering managers that centres on how you contribute to a team and manage projects. The reported description says the focus moves away from pure technical execution toward working with others, and the role itself involves code reviews, pair programming and Scrum-style teams. Expect to talk about your own work history in detail.
What to demonstrate
- Contribution to a team, as candidates describe the stage
- Project management experience, including Agile or Scrum practice
- Your account of past projects and the technical challenges in them
How to prepare
- Write a STAR outline for a team conflict and for working to a tight deadline in an Agile team, each ending with a result and a lesson.
- Choose two projects and be able to sketch their architecture, say which parts you owned, and describe the hardest technical problem and how you resolved it.
- Have a concrete example of giving or receiving a code review or pairing session, since both are named as part of the work.
Final Leadership Interviews
Candidates describe a possible final meeting with a director that looks at how well you understand business impact and at overall fit. After the technical rounds, the story you tell about your work matters more: what the software changed for its users and the business, and how you decided between options.
What to demonstrate
- Understanding of business impact, as candidates describe the stage
- Overall fit with the team and the role
- Consistency between what you explained in earlier technical conversations and what you say now
How to prepare
- For each of your two main projects, write the user or business problem, your decision, and an outcome you can verify, without rounded or invented numbers.
- Learn the basics of how airlines and freight forwarders use cargo software, and relate Cargospot and AI Hub to what you would build.
- Prepare questions about how the Java platform work and the Python AI services fit together, and re-read your own technical answers so you repeat them consistently.
Where candidates lose points
Giving definitions for the Java fundamentals questions (interface versus abstract class, final, finally and finalize) with no decision rule or example
For each concept give a rule you apply: an interface for a capability contract that several unrelated classes meet, an abstract class for shared state and partial implementation. Show final on a variable, method and class, and finally running even after a return. Note that finalize is not a reliable cleanup mechanism, and name try-with-resources as the replacement. Add one example from your own code.
Answering the slow-production-code question by naming a rewrite or a data structure before measuring anything
Open with the method: reproduce the problem, collect timings or a profile, find the real hot spot (a query, allocation, lock contention, a remote call), change one thing and measure again. Then give the fix and the trade-off.
Fixing the first bug in the snippet and stopping, or rewriting the whole snippet without explaining
Read it once and say what it is meant to do, then go through the categories: boundaries, nulls, equality and hashing, resource leaks, shared mutable state. For each defect state the effect, the fix and the test that would have caught it.
Answering the cargo-tracking API design question with a list of endpoints and no clarifying questions
Ask who calls the API and what they need to know. Then define the resources (for example shipments and status events), pagination, the error format, idempotent writes, authentication and a versioning plan. Say what happens when a caller retries after a timeout.
Telling project stories entirely in terms of "we", or without any business outcome, in the managers and leadership conversations
Prepare two projects with your own decisions, the trade-offs you weighed, and an outcome you can verify. Know the architecture well enough to draw it, and connect it to a user or business problem.
Questions & practice
How does memory management work in Java, and what is the role of the Garbage Collector?
Medium · Java Fundamentals
Approach
- Map the memory areas. Objects and arrays live on the shared heap. Each thread has its own stack of frames holding local primitives and references. Class metadata lives in Metaspace, which replaced PermGen in Java 8.
- Explain reachability: the collector traces from GC roots (live thread stacks, static fields, JNI references) and reclaims whatever it cannot reach. This is not reference counting, so unreachable cycles are collected too.
- Describe generational collection. New objects go to Eden. Minor collections copy survivors between survivor spaces and promote long-lived objects to the old generation. Name the collectors and the trade-off between them: Parallel for throughput, G1 (the default since JDK 9) for balanced pauses, ZGC and Shenandoah for very short pauses.
- Point out that leaks still happen through references that stay reachable: static or unbounded caches, listeners nobody deregisters, ThreadLocals on pooled threads. Diagnose with GC logs (-Xlog:gc), a heap dump (-XX:+HeapDumpOnOutOfMemoryError or jcmd GC.heap_dump) and a dominator-tree view in a heap analyzer.
- Close with the caveats. System.gc() is only a hint. finalize() is deprecated. Soft and weak references let caches give memory back when the collector needs it.
Follow-up
- How do 'OutOfMemoryError: Java heap space' and 'OutOfMemoryError: Metaspace' differ, and what would you check for each?
- A latency-sensitive service shows long GC pauses. Which flags and which collector would you look at first?
- What is the difference between a StackOverflowError and a heap OutOfMemoryError?
Write a program to display shapes or patterns efficiently on the screen.
Medium · Problem Solving and Coding
Approach
- Clarify the shape and the input: pyramid, diamond, hollow square or Pascal's triangle, the size n, and what to do with n <= 0 or with an even height for a diamond.
- Derive a formula for each row instead of tuning loops by trial. For a centred pyramid, row i (counting from 0) has n-1-i leading spaces and 2i+1 stars. For hollow shapes, print a star only on the boundary (first or last row, first or last column) and a space everywhere else.
- Make the output efficient. The output itself has Θ(n²) characters, so O(n²) time is the lower bound. Build each line in a StringBuilder, or use String.repeat in Java 11+, and write through a BufferedWriter or PrintWriter with one flush. Calling System.out.print once per character is slow because every call goes through the synchronized PrintStream.
- Keep the shape logic separate from the printing. A method that returns List<String> (or a charAt(row, col) rule) can be unit-tested. Use symmetry: the lower half of a diamond reuses the upper rows in reverse.
- For Pascal's triangle, compute each row in place with C(n,k+1) = C(n,k)·(n-k)/(k+1), multiplying before dividing so the division is exact. Use long once rows pass about 30, because the values overflow int.
Follow-up
- How would you print a hollow diamond, and which conditions change compared with the filled one?
- How would you write a unit test for the pattern without capturing standard output?
- If n is very large, how do you avoid building the whole output in memory?
How would you optimize a piece of code that is performing poorly in a production environment?
Medium · Problem Solving and Coding
Approach
- Measure before changing anything. Pin down the symptom with numbers (p95/p99 latency, throughput, CPU, heap and GC time, error rate) and find when it started, so you can check it against deploys, data growth or traffic changes.
- Find where the time goes. On the JVM use Java Flight Recorder or async-profiler for CPU and allocation, and several jstack thread dumps to spot lock contention or threads blocked on I/O. In Python use cProfile or py-spy. Classify the problem as CPU-bound, I/O-bound, GC-bound or contention-bound.
- Fix the dominant cause with the matching technique. Replace a nested-loop lookup (O(n·m)) with a HashMap (O(n+m)). Remove N+1 queries by batching or joining. Add the missing index after reading the EXPLAIN (ANALYZE) plan. Cut allocation churn in hot loops. Batch chatty remote calls or cache them, and decide how stale the cache may be.
- Verify the fix. Use JMH for micro-benchmarks and a load test for end-to-end changes, then compare against the original numbers. Ship behind a flag or to a canary, and watch the same dashboards so you can confirm the gain and catch regressions.
- State the trade-offs: caches cost memory and invalidation effort, parallelism adds contention, and a faster query can slow down writes if it needs more indexes.
Follow-up
- The slowdown appears only in production and you cannot reproduce it locally. What do you collect, and how?
- How do you tell whether a latency spike comes from GC pauses or from a slow downstream dependency?
- After your fix, p50 improved but p99 got worse. What do you investigate?
Given a code snippet, identify the bugs and explain how you would resolve them.
Medium · Problem Solving and Coding
Approach
- Read for intent first. State what the code should do and its contract (inputs, outputs, nulls, thread safety). Then trace it by hand with small inputs that include edge cases: empty, null, a single element, boundary values.
- Check common Java bug classes in order. Off-by-one loop bounds. Comparing Strings or boxed Integers with == instead of equals (Integer caches only -128 to 127, so == seems to work for small values). Unchecked nulls. Integer overflow, as in (lo + hi) / 2 versus lo + (hi - lo) / 2.
- Then look for runtime and resource bugs. A ConcurrentModificationException from removing elements inside a for-each loop (fix with Iterator.remove or removeIf). Streams or connections left open (use try-with-resources). equals overridden without hashCode, which breaks HashMap lookups. Empty catch blocks that swallow exceptions. Shared mutable state such as HashMap or SimpleDateFormat used from several threads.
- For each bug, say what input triggers it, what goes wrong and the smallest fix. Write a failing unit test before changing the code so the fix can be checked. Fix correctness first and mention style issues separately.
Follow-up
- Write the unit test that would have caught the most serious bug you found.
- Is your fixed version thread-safe if two threads call it at once?
- Which compiler warnings or static-analysis rules (for example SpotBugs) would have flagged these bugs?
Denormalise tenant onto revisions and backfill it live
Hard · denormalisation · online migration · backfill
resource_revision (revision_id, resource_id, version, actor_user_id, change_kind, patch, request_id, created_at) has 400M rows and no tenant column; tenant_id lives only on resource. Two reads need it: a tenant-scoped audit feed ordered by created_at DESC, and an offboarding purge. Both join back to resource today. Justify adding tenant_id to resource_revision against those two reads, name the anomaly the copy introduces and the constraint that prevents it, then give the ordered migration for a live table taking 1.2k writes/second — the lock each step takes, how the backfill is batched, and where each step stops being reversible. PostgreSQL 16.
Approach
- Justify from the access path rather than from taste. Without the column, the audit feed either scans resource_revision by created_at and discards other tenants' rows, or resolves the tenant's resource_ids first and probes with them — both proportional to the tenant's whole history rather than to one page. With (tenant_id, created_at DESC, revision_id DESC) it is a seek that stops at 50 rows, and the purge becomes a ranged delete instead of a join.
- Name the cost exactly: a second copy of a fact can disagree with the first. Make the disagreement unwritable rather than documented — add UNIQUE (resource_id, tenant_id) on resource so it can serve as a foreign-key target, then FOREIGN KEY (resource_id, tenant_id) REFERENCES resource (resource_id, tenant_id) on the revision table. A revision can then only ever carry its parent's tenant.
- Step one, expand: ALTER TABLE resource_revision ADD COLUMN tenant_id BIGINT NULL, with no default, so it is a catalogue change and no rewrite. It still needs ACCESS EXCLUSIVE for an instant, and that instant queues behind the longest open transaction on the table while every later query queues behind it — set lock_timeout to 2s and retry rather than wait.
- Step two, dual-write: deploy the writer that populates tenant_id on every new revision while reads still use the join. Reversible by redeploying the previous build, because nothing reads the column yet.
Follow-up
- The backfill is half finished and a rollback is required. What state is the table in, and what does the previous build do with a half-populated column?
- How do you verify the backfill actually finished, given rows are still being inserted while it runs?
Explain why the owner filter ignores the listing index
Medium · composite index · query plans · sort elimination
The only index on resource is (tenant_id, status, updated_at DESC, resource_id DESC). A new endpoint returns one user's resources across all statuses, newest created first: WHERE tenant_id = $1 AND owner_user_id = $2 ORDER BY created_at DESC LIMIT 20. On a tenant with 2M rows it takes 900 ms and EXPLAIN shows a sort above a large scan. Explain precisely why the existing index cannot serve it, give the index that can, and state which of these the new index still will not help: owner_user_id alone across tenants; the same query ordered by updated_at. PostgreSQL 16.
Approach
- Separate the two jobs an index does. For filtering, a composite btree is seekable only on a left prefix, so with no predicate on status the scan can at best range over tenant_id and test owner_user_id per row; PostgreSQL 16 has no btree skip scan to jump the unconstrained column.
- For ordering, the index is sorted by (status, updated_at) within a tenant and not by created_at, so the LIMIT cannot stop early: every matching row is read and then sorted. That is the 'Sort Method: top-N heapsort' line, and it is why the plan reads 2M rows to answer with 20.
- Derive the replacement from the access path — equality, equality, then the ordering column: CREATE INDEX CONCURRENTLY ON resource (tenant_id, owner_user_id, created_at DESC). The scan seeks to the (tenant, owner) range and walks 20 entries in order, so the Sort node disappears along with the row-read.
- Treat INCLUDE (title, status) as conditional, not free. An index-only scan still visits the heap for any row whose page is not marked all-visible, so on a table taking 1.2k writes/second the win depends on autovacuum keeping the visibility map current, and the wider index costs more on every insert.
Follow-up
- 90% of rows are status='active'. Would a partial index WHERE status = 'active' change your answer, and for which of the three queries?
- A dashboard runs this for 40 owners in one page load. What changes about the design?
Explain the difference between an interface and an abstract class in Java.
Medium · Java Fundamentals
Approach
- Start with the type rule: a class can extend only one abstract class but implement many interfaces. An abstract class can have constructors, instance fields, protected or package-private members, and both abstract and concrete methods.
- Give the modern interface rules: since Java 8 interfaces can have default and static methods, and since Java 9 private methods. Their fields are implicitly public static final, they have no constructors and they hold no per-instance state.
- Choose by intent. Use an interface for a capability that unrelated types share (Comparable, Runnable, a Repository contract). Use an abstract class for closely related types that share state or a template-method skeleton, where the base class fixes the algorithm and subclasses fill in the steps.
- Cover the diamond case: if a class inherits the same default method from two interfaces, it must override it, and it can delegate with InterfaceName.super.method(). Also note that an interface with exactly one abstract method can be the target of a lambda.
Follow-up
- Can an abstract class have a constructor if it can never be instantiated, and when does that constructor run?
- You need to add a method to an interface that many classes already implement. How do you avoid breaking them?
- When would you choose a sealed interface (Java 17) over an abstract class?
Can you describe the principles of OOP and how you apply them in your daily work?
Medium · Java Fundamentals
Approach
- Name the four principles in one line each. Encapsulation hides state behind methods that protect invariants. Abstraction exposes what a component does, not how it does it. Inheritance reuses behaviour through an is-a relationship. Polymorphism means one call site dispatches to the right implementation at runtime.
- Ground each one in your own code. For example: private fields with validation in a constructor or factory, a strategy interface with one implementation per pricing or routing rule picked at runtime, and an abstract base class that removes duplicated handling.
- Mention the limits. Prefer composition over inheritance when the is-a relationship is weak, because deep hierarchies couple subclasses to base-class internals. Use Square extending Rectangle to show a Liskov substitution violation.
- Connect the principles to SOLID and to testing. Coding to interfaces lets you inject fakes in unit tests, and single-responsibility classes are easier to change without touching unrelated behaviour.
Follow-up
- What is the difference between overloading and overriding, and which one is resolved at compile time?
- How would you refactor a large legacy class that violates the single-responsibility principle without breaking its callers?
- When has inheritance caused you a problem, and what did you replace it with?
Explain the significance of the "final," "finally," and "finalize" keywords.
Medium · Java Fundamentals
Approach
- Start by saying the three are unrelated despite the similar names. final is a modifier, finally is a block, and finalize is a method on Object.
- final: a final variable can be assigned only once, but a final reference does not make the object immutable (a final List can still be modified). A final method cannot be overridden, and a final class such as String cannot be subclassed. Lambdas and anonymous classes may capture only final or effectively final locals. Final fields also get safe-publication guarantees once the constructor finishes, as long as 'this' does not escape during construction.
- finally: the block runs after try/catch whether or not an exception is thrown, including when the try block returns. It does not complete if System.exit is called or the JVM halts. A return inside finally replaces the try block's return value and discards any exception in flight, so avoid it.
- Prefer try-with-resources (Java 7+) for anything AutoCloseable. Resources close in reverse order, and exceptions thrown during close are attached to the primary exception and can be read with getSuppressed().
- finalize: the collector may call it before it reclaims an object, with no guarantee of when or whether that happens. It has been deprecated since Java 9 and marked for removal by JEP 421 (Java 18). Use try-with-resources or java.lang.ref.Cleaner instead.
Follow-up
- What does this method return if try returns 1 and finally returns 2, and what happens to an exception thrown in try?
- Is a private static final List thread-safe and immutable? How would you make it so?
- Why was finalize deprecated, and what problems did it cause in practice?
How would you approach designing an API for a specific cargo-tracking requirement?
Medium · Problem Solving and Coding
Approach
- Clarify the requirement and the callers first. Is it a public read API for shipment status, an ingestion API where partners post events, or both? Settle the identifier (for example the 11-digit air waybill number), the read and write volumes, and how fresh the data must be.
- Model the resources around an append-only event log: GET /v1/shipments/{awb} returns the current status, derived from the events, and GET /v1/shipments/{awb}/events?cursor=... returns history with cursor pagination. Each event stores both event time and received time, so events that arrive late or out of order still sort correctly.
- Make writes safe to retry. POST /v1/shipments/{awb}/events takes an Idempotency-Key header (or a natural key such as source plus event id), backed by a unique constraint. A retry after a timeout then returns the original result and does not create a duplicate event.
- Design the contract details. Define an error taxonomy (400 for validation, 404 versus 403 so the API does not reveal which shipments exist, 409 for conflicts, 429 with Retry-After). Use OAuth2 client credentials with tenant scoping so each caller sees only its own shipments. Version through /v1 or a header and make only additive changes within a version.
- For push updates, compare polling with webhooks. Webhooks need signed payloads, at-least-once delivery with backoff, and receivers that tolerate duplicates. Back the API with indexed (awb, event_time) storage and a cached current-status projection so the hot read path stays cheap.
Follow-up
- Two status events for the same shipment arrive out of order or twice. What does the API return, and what does it store?
- How would you notify thousands of subscribers about status changes without polling?
- You need to rename a field that clients already use. How do you roll that out?
Describe your process for debugging a complex issue in a distributed system.
Medium · Problem Solving and Coding
Approach
- Scope the problem before theorising: which endpoints, tenants or regions are affected, since when, and whether every request fails or only some. Line the start time up against deploys, config changes, traffic shifts and dependency incidents.
- Follow one failing request across services with a correlation or trace ID, using distributed tracing such as OpenTelemetry and centralised logs. Use per-service rate, error and duration metrics to find the first hop where things go wrong, as opposed to the hops that only pass the error along.
- Check the failure modes that are specific to distributed systems. Retries that multiply load. Timeout budgets that do not match between caller and callee. Partial failures that leave data half-written. Non-idempotent handlers replayed by a queue. Clock skew between hosts when you compare log timestamps. On Docker or OpenShift, also check container restarts, OOMKilled status and failing readiness probes.
- Mitigate first (roll back, turn off a feature flag, shed load), then find the root cause. Narrow down by service boundary or by change, and reproduce in staging with fault injection or the traffic shape that triggered it. Separate the trigger from the underlying defect.
- Close the loop. Add the metric, log field or alert that would have exposed the problem sooner, write a regression test, and record the timeline and follow-up actions in a blameless postmortem.
Follow-up
- The error is intermittent and appears only under peak load. How do you reproduce it?
- Two changes shipped at about the time the errors started. How do you tell which one is the cause and which is coincidence?
- What would you add to the system's observability so the next incident takes less time to diagnose?
Suggested practice checklist
The plan follows the reported loop: Java theory, live coding and debugging, then API and stack topics, and finally the managers' and leadership conversations. Each day produces something you can check, and the questions practised that day are attached to it.
Day 1 — Map the loop and the stack
- Write the four reported rounds and what each covers, then mark the format you are least ready for: theory exam, live coding, debugging or the leadership conversation.
- List the technologies candidates mention (Java and Spring Boot, Python, Docker, OpenShift, GitLab CI, RAG and prompt engineering) and rate each as strong, rusty or new.
- Read the company's public pages on Cargospot and the AI Hub, and write three questions you would ask the team.
Deliverable: A one-page loop map, a rated technology list and three questions for the team.
Day 2 — Java fundamentals: types, OOP and keywords
- Write a code example showing when you would choose an interface and when an abstract class, including default methods and shared state.
- Write an answer on the principles of OOP using code from a real project of yours, with one place where you broke a principle on purpose.
- Write small snippets for final on a variable, method and class, finally running after return, and why finalize is replaced by try-with-resources.
Deliverable: A cheat sheet with a runnable example and a spoken one-paragraph answer for each of the three Java topics.
Day 3 — Memory, garbage collection and threads
- Draw stack versus heap, object reachability from GC roots and the generations of the heap, and write what makes an object collectable.
- Write a small program with an ExecutorService showing that execute() reaches an uncaught exception handler while submit() hides the failure in the Future until get().
- Add a try/finally that releases a lock and a handler that restores the interrupt flag, and run it to confirm.
Deliverable: A memory diagram, a runnable executor demo, and a spoken answer for the garbage collection and thread-exception questions.
Day 4 — Live coding and bug-hunting
- Write pattern-printing programs (a right triangle, a pyramid, a diamond) in your main language with nested loops and a StringBuilder or join, and test sizes of zero, one and an even number.
- Write three short buggy snippets of your own (off-by-one, missing hashCode, unclosed resource) and fix each with a test.
- Do the pattern exercise once aloud, stating assumptions and edge cases before you write.
Deliverable: Three pattern programs with tests and three bug write-ups (bug, cause, fix, test).
Day 5 — Performance and distributed debugging
- Write a slow function, profile it, fix the main hot spot and record the before and after timings.
- Write a debugging runbook for a failure across services: what changed, correlation ids across logs, narrowing by bisection, separating the trigger from the cause.
Deliverable: A measured before-and-after note for the slow function and a one-page runbook for distributed debugging.
Day 6 — API design, architecture and the AI Hub stack
- Write a design for a cargo-tracking API: resources, endpoints, pagination, idempotent writes, error format and versioning.
- Answer the example scenarios candidates describe: processing high-volume cargo data in a service, handling a production service failure, and relational versus NoSQL storage for cargo data.
- Sketch a Dockerfile for a Spring Boot or Python service and the stages of a GitLab CI pipeline, then outline a RAG flow in plain words (split, embed, retrieve, prompt).
Deliverable: An API spec page, a container and CI outline, and a short written trade-off on relational versus NoSQL storage.
Day 7 — Behavioral outlines and a full mock
- Write STAR outlines for the five behavioral questions: why CHAMP Cargosystems, a team conflict, staying current while maintaining systems, a project you are proud of, and a tight Agile deadline.
- Rehearse the outlines aloud and shorten each to the decision, the trade-off and the result.
- Run a mock session mixing one Java theory question, one coding exercise, one design question and one behavioral prompt, and note what to fix.
Deliverable: Five STAR outlines and notes from one full mock session.
Behavioral and team-fit preparation
Candidates describe the later rounds, with engineering managers and possibly a director, as covering team contribution, project management, business impact and overall fit. The role also involves code reviews, pair programming and Scrum, with colleagues in different offices. Prepare stories where you made a decision, weighed a trade-off and can state a result.
- Describe a project you are particularly proud of and your role in its success.
- Walk through the architecture of a past project and the hardest technical challenge you met in it.
How do you handle exceptions in a multi-threaded Java application?
Medium · Java Fundamentals
Approach
- Start with the rule that an exception belongs to the thread that throws it: it never travels back to the thread that started the work. In a raw Thread an uncaught exception ends that thread, so set an uncaught exception handler (per thread or as the default) that logs the thread name and context.
- Know the executor behavior. With execute(), an exception escaping the task reaches the uncaught exception handler and the pool replaces the worker. With submit(), it is stored in the Future and appears only when you call get(), wrapped in an ExecutionException, so a Future nobody reads hides the failure. Call get(), unwrap getCause(), and use a timeout.
- For CompletableFuture chains, attach exceptionally, handle or whenComplete at the end; downstream stages may see the error wrapped in a CompletionException, and a chain with no terminal handler fails silently.
- Protect shared state: release locks in finally, use try-with-resources, and leave data consistent when a task dies midway. Never swallow InterruptedException: either propagate it or restore the flag with Thread.currentThread().interrupt(). For scheduled tasks, wrap the body in try/catch, because an uncaught exception cancels all later runs.
- State a policy: catch at the task boundary where you can act (retry, skip, fail the batch), log with a correlation id, and do not catch Throwable blindly, since errors such as OutOfMemoryError are not recoverable.
Follow-up
- What happens to an exception thrown inside a task passed to submit() if nobody ever calls get()?
- How would you stop one failing task in a parallel batch from hiding the results of the others?
- Why do you restore the interrupt flag after catching InterruptedException instead of just logging it?
Why are you interested in joining CHAMP Cargosystems specifically?
Medium · Behavioral and Cultural Fit
Approach
- Build the answer from three layers you can defend: the domain (software for the air cargo chain used by airlines and forwarders, and why that data or those workflows interest you), the technical fit (your Java/Spring Boot or Python experience, plus Docker, GitLab CI or GenAI work if you have it), and the working style (Scrum teams and collaboration across offices, which candidates mention).
- Name something specific you can learn about: Cargospot or the AI Hub. Explain what you would want to build or improve there, and tie it to a project of yours. A concrete link is stronger than praise.
- Be honest about the stack gap. If you are strong in Java and light on generative AI, say what you have already done to close it, such as building a small RAG prototype.
- The mistake that sinks it is a generic answer (good reputation, global company) that would fit any employer, or one about perks and location only. Cut any sentence that you could say unchanged about another company.
Follow-up
- Which interests you more, the established Java platform work or the AI Hub, and why?
- What would you want to learn in your first months in the role?
- What other options are you considering, and why does this one rank where it does?
Describe a time you had to resolve a conflict within your development team.
Medium · Behavioral and Cultural Fit
Approach
- Choose a technical disagreement (a design choice, a review comment, an estimate, a branching or release approach) rather than a personality clash. Give the situation in two sentences, then name the competing positions fairly, including the other person's.
- Show your actions in order: you restated their position to check you understood it, moved the discussion to shared criteria (latency, risk, maintainability, deadline), and settled it with evidence such as a quick prototype, a benchmark or a test, not by seniority or persistence.
- State the outcome and the relationship afterwards: what was decided, what it did to the project, and how you worked together after. If the decision went against you, say so and show you committed to it.
- The mistake that sinks it is a story where you were simply right, or one where the conflict was avoided rather than resolved. If teams span offices, a time-zone or ownership conflict is a credible example.
Follow-up
- What would you have done if the other person had still disagreed after seeing the evidence?
- How did you work with that person afterwards?
- When do you involve the manager, and when do you handle it between the two of you?
How do you stay updated with new technologies while maintaining existing systems?
Medium · Behavioral and Cultural Fit
Approach
- Answer with a system, not a list of blogs: release notes for the Java and Spring Boot versions you run, one small experiment at a time (for example a RAG prototype in Python), and a way to share findings with the team such as a short write-up or a review-session demo.
- Show the maintenance side with a story: something you learned that you then applied to an existing system safely, with tests first, a small scope, a feature flag or rollback path, and a stated result.
- State your criteria for adoption: maintenance cost, team skills, support lifetime, and the risk to running systems. Include something you evaluated and chose not to adopt, and why.
- The mistake that sinks it is naming sources with no outcome, or implying you always move to the newest tool. The question is about balancing new learning against systems that must keep running.
Follow-up
- Tell me about something you learned and decided not to adopt.
- How would you introduce a new library or framework into a legacy Java service?
- How do you share what you learn so it does not stay with one person?
Tell us about a project you are particularly proud of and your role in its success.
Medium · Behavioral and Cultural Fit
Approach
- Pick a project whose architecture you can draw and defend, ideally with an API, a database and a deployment path (Docker, a CI pipeline), because candidates are told to be ready to explain the architecture and technical challenges of past work.
- Structure it: the problem and goal in two sentences; your role versus the team's (say "I" for what you decided and built, and name teammates for the rest); two or three main components; the hardest technical problem, the alternatives you rejected and the trade-off; the result.
- Give an outcome you can verify, such as a defect rate, a latency or a delivery date, and be exact about how it was measured. Do not round up or invent figures.
- Close with what you would change now. The mistake that sinks it is a story told only in terms of the team, with no personal decision, or one where deeper questions about the design expose that you did not own it.
Follow-up
- What was the hardest technical decision, and which alternative did you reject?
- What would you change if you rebuilt it today?
- How was it tested and deployed, and how did you know it was working in production?
How do you handle tight deadlines in an Agile environment?
Medium · Behavioral and Cultural Fit
Approach
- Use a story where the deadline forced a trade-off. Show that you clarified with the product owner what the date was tied to, split the work into the smallest shippable increment, and made the cut scope visible in sprint planning or the board.
- Show how you protected quality: tests and review kept on the risky parts, an early warning to stakeholders when the risk appeared, and a decision about what to defer rather than rushing everything.
- Describe the follow-up: the shortcuts you took were recorded, scheduled and paid back, and the result (delivered date, defects after release) is stated.
- The mistake that sinks it is a heroic overtime story with no trade-off, or one that blames the product owner or the estimate. Show negotiation and communication, not just effort.
Follow-up
- What exactly did you cut, and who agreed to it?
- How did you handle the technical debt afterward?
- What would you have done if the product owner had refused to reduce scope?