Java SE 7 OCP Training Lab: Real-World Coding ExercisesPreparing for the Java SE 7 Oracle Certified Professional (OCP) exam demands more than memorizing APIs and syntactic rules — it requires fluency gained through solving realistic coding problems that mirror the exam’s scope and the tasks you’ll face in real projects. This article presents a comprehensive, structured training lab focused on real-world coding exercises designed to increase your depth of understanding, sharpen problem-solving skills, and build confidence for both the certification exam and everyday Java development.
Why a hands-on training lab matters
Reading books and watching videos builds familiarity, but active practice cements learning. A hands-on lab:
- Reinforces API usage and nuances (for example, Collections, generics, exception handling, and concurrency).
- Reveals subtle behaviors (autoboxing, floating-point quirks, equals/hashCode contracts).
- Trains you to apply concepts under time pressure — a proxy for exam and workplace conditions.
- Helps you develop debugging strategies and testing habits.
Key focus areas for Java SE 7 OCP include: language fundamentals, class design, generics and collections, concurrency, I/O (NIO.2 additions in Java 7), localization, JDBC, and best practices.
Lab structure and progression
A good training lab follows a progressive structure so each exercise builds on previous knowledge:
- Fundamentals review (syntax, control flow, primitives, boxing/unboxing, strings).
- Object-oriented design tasks (inheritance, interfaces, visibility, inner classes).
- Generics and collections exercises (wildcards, raw types, List/Map/Set behavior).
- Exception handling and assertions (checked vs unchecked, try-with-resources).
- I/O and NIO.2 (file operations, Path/Files, streams).
- Concurrency (Thread, Runnable, Executors, locks, concurrency utilities).
- JDBC and transactions (connections, prepared statements, result sets).
- Integration scenarios (combine areas into larger, realistic projects).
- Timed mock exam coding challenges.
Each module contains multiple exercises: warm-up (10–20 minutes), main problems (30–90 minutes), and extension tasks for deeper exploration.
Example exercises (detailed)
Below are representative exercises you can use in the lab. Each includes the objective, sample input/expected behavior, hints, and extension ideas.
Exercise A — String and primitive quirks (warm-up)
- Objective: Demonstrate understanding of string pooling, equality, and autoboxing.
- Task: Write a method that receives an array of Object where elements may be Integer, Long, or String. Return a list of unique numeric values (as Long) present in the array, interpreting numeric strings appropriately, ignoring values that cannot be parsed. Maintain insertion order.
- Expected behavior:
- Input: [Integer(5), “5”, Long(6), “abc”, Integer(5)] → Output: [5L, 6L]
- Hints: Use LinkedHashSet for order and uniqueness; handle NumberFormatException.
- Extensions: Support hex (0x) and binary (0b) string formats as per Java 7 Integer/Long parsing.
Exercise B — Collections and generics (main)
- Objective: Master wildcard capture, PECS (“Producer Extends Consumer Super”), and concurrent collections.
- Task: Implement a utility method: public static
void copyElements(Collection<? super T> dest, Collection<? extends T> src) that safely copies elements while preserving insertion order when possible. - Expected behavior: Copies elements from src to dest without ClassCastException when used properly.
- Hints: Understand generic bounds; test with List
and List . - Extensions: Add overloads for copying into concurrent collections (ConcurrentLinkedQueue) and preserve thread-safety.
Exercise C — Exceptions, try-with-resources (main)
- Objective: Use try-with-resources and understand suppressed exceptions.
- Task: Create a method that reads two files containing integers (one integer per line), sums corresponding lines, and writes results to an output file. Use try-with-resources and ensure suppressed exceptions are logged but do not lose primary exceptions.
- Expected behavior: Properly close resources; if both reader.close() and writer.close() throw, primary exception remains and the other is suppressed.
- Hints: Use java.util.logging or printStackTrace to show suppressed exceptions via Throwable.getSuppressed().
- Extensions: Handle mismatched lengths by throwing a custom checked exception.
Exercise D — NIO.2 file operations (main)
- Objective: Practice java.nio.file.Path and Files utilities.
- Task: Implement a utility that scans a directory tree and produces a report of duplicate files (by content) using SHA-256 hashes. Provide options to follow or ignore symbolic links.
- Expected behavior: List groups of files that have identical content; skip empty files if specified.
- Hints: Use Files.walkFileTree or Files.find and MessageDigest for SHA-256. Pay attention to performance and memory (streaming reads, buffering).
- Extensions: Add an option to hardlink duplicates to a single file to save space (careful with atomic moves and file system differences).
Exercise E — Concurrency and synchronization (main)
- Objective: Demonstrate thread-safety, volatile, synchronized, and ExecutorService usage.
- Task: Implement a thread-safe bounded cache with least-recently-used (LRU) eviction. Provide get(key) and put(key, value) methods and an optional loader to compute missing values atomically.
- Expected behavior: Multiple threads can get/put concurrently; only one thread computes a value for a missing key.
- Hints: Use ConcurrentHashMap plus a concurrent linked structure or wrap LinkedHashMap with synchronized blocks. For loader, use computeIfAbsent semantics or a Future-based approach.
- Extensions: Add time-to-live (TTL) for entries and a background cleanup thread using ScheduledExecutorService.
Exercise F — JDBC basics (main)
- Objective: Understand JDBC resource management and transaction boundaries.
- Task: Write a DAO method that transfers funds between two accounts in a relational DB (update balances). Ensure ACID behaviour and proper exception handling with rollbacks.
- Expected behavior: Either both updates succeed or the database remains unchanged on failure.
- Hints: Use Connection.setAutoCommit(false), try-with-resources for PreparedStatement, finally for connection commit/rollback.
- Extensions: Implement optimistic locking using a version column and retry logic.
Exercise G — Integration project (capstone)
- Objective: Combine I/O, concurrency, and JDBC into a small application: a concurrent file processor that reads CSV files dropped into a directory, validates records, persists valid rows to a database, and moves processed files to archive or error folders.
- Requirements:
- Use WatchService to detect new files.
- Process multiple files in parallel but preserve ordering inside each file.
- Use a thread pool to limit concurrent work.
- Maintain idempotency so rerunning doesn’t duplicate data.
- Hints: Use transactional inserts and a processed-files table to record completed filenames; design careful exception-handling and recovery logic.
- Extensions: Add metrics (processed count, errors) exposed via a simple HTTP endpoint.
Example solutions and pitfalls (concise)
- Generics: Watch for runtime casting pitfalls; raw types bypass compile-time checks and often hide bugs.
- equals/hashCode: Ensure consistent implementation; failing this breaks collections like HashMap.
- Concurrency: Avoid synchronized-heavy designs that degrade throughput; prefer java.util.concurrent utilities.
- I/O: Use buffered streams and watch for character encoding issues; prefer NIO.2 for file system operations.
- JDBC: Always close ResultSet and PreparedStatement (try-with-resources) and manage transactions explicitly when performing multi-step updates.
Measuring progress and exam readiness
- Maintain a progress log with completed exercises, time spent, and mistakes made.
- Simulate exam conditions: solve several medium-to-hard exercises within fixed time windows.
- After each exercise, write unit tests (JUnit) that validate edge cases and expected behavior.
- Peer review or pair-programming amplifies learning—explain your solution to someone else.
Tools, libraries, and environment
- Java SE 7 (OpenJDK 7) or a compatible JDK for accurate behavior.
- Build: Maven or Gradle (use maven-compiler-plugin with source/target 1.7).
- Testing: JUnit 4.x.
- Logging: java.util.logging or SLF4J with a simple backend.
- DB: H2 or SQLite for lightweight JDBC practice.
- IDE: IntelliJ IDEA, Eclipse, or NetBeans for debugging and quick iterations.
- Optional: Git for version control and reproducible exercise history.
Sample weekly training plan (8 weeks)
Week 1: Fundamentals, strings, primitives, and basic exercises.
Week 2: OOP, class design, inner classes, serialization basics.
Week 3: Generics and collections deep dive.
Week 4: Exceptions, I/O, and try-with-resources.
Week 5: NIO.2, file processing, and hashing.
Week 6: Concurrency patterns, executors, and thread-safety.
Week 7: JDBC, transactions, and integration with file processing.
Week 8: Capstone project, timed mocks, and review of weak areas.
Common mistakes and how to avoid them
- Relying on memorization — practice behavior with code.
- Ignoring edge cases — create tests for nulls, empty collections, and large inputs.
- Over-synchronization — prefer concurrent collections and lock-free approaches when possible.
- Neglecting resource closure — use try-with-resources and always test failure paths.
- Skipping version-specific features — test on Java 7 to ensure behaviors (e.g., try-with-resources, diamond operator limitations compared to later Java versions).
Final tips
- Practice reading and understanding API docs quickly — the exam often tests knowledge of method contracts and exceptions thrown.
- Write small, focused unit tests that capture edge cases.
- Timebox practice sessions and simulate exam conditions periodically.
- Keep a notebook of tricky behaviors you encounter; reviewing these before the exam is high-leverage.
This training lab blueprint plus the exercises above will prepare you to both pass the Java SE 7 OCP exam and become a stronger Java developer by emphasizing realistic, integrative coding tasks rather than isolated facts.