Skip to main content

Advanced Java Patterns

Beyond basic usage, BBj can implement Java interfaces, handle Java exceptions gracefully, and access external libraries through classpath configuration. These patterns unlock the full power of the Java ecosystem from BBj code.

Implementing Java Interfaces

BBj classes can implement Java interfaces using the implements keyword. This is the bridge between BBj code and Java APIs that expect callback objects, strategy patterns, or other interface-based contracts.

Here is a Comparator implementation that sorts strings by length:

use java.util.Comparator
use java.util.Collections
use java.util.ArrayList

class public LengthComparator implements Comparator
method public int compare(Object o1!, Object o2!)
len1 = len(str(o1!))
len2 = len(str(o2!))
if len1 < len2 then methodret -1
if len1 > len2 then methodret 1
methodret 0
methodend
classend

rem Create a list of strings
list! = new ArrayList()
list!.add("banana")
list!.add("fig")
list!.add("cherry")
list!.add("apple")

rem Sort using the BBj Comparator implementation
Collections.sort(list!, new LengthComparator())

rem Print sorted results
for i = 0 to list!.size() - 1
print list!.get(i)
next i
rem Output: fig, apple, banana, cherry

The key points:

  • The BBj class declares implements Comparator
  • The method signature must match the Java interface exactly
  • The BBj object can then be passed to any Java API expecting that interface
  • Java calls back into your BBj code through the interface methods

Generics: Raw Types Only

BBj does not support Java generics syntax. Always use raw types:

use java.util.HashMap
use java.util.ArrayList

rem Correct -- raw types
map! = new HashMap()
list! = new ArrayList()

Attempting to use angle brackets causes a syntax error:

rem WRONG -- this will NOT compile in BBj
rem map! = new HashMap<String, String>()
rem list! = new ArrayList<Integer>()

BBj resolves types at runtime, not at compile time. This means there is no compile-time type safety for Java generic types -- you are responsible for putting and getting consistent types. If you add a string to a list and then try to use the retrieved value as a number, you will get a runtime error, not a compile error.

Handling Java Exceptions (Error 252)

When a Java method throws an exception, BBj traps it as error 252. You handle it with ERR= or SETERR -- BBj does not have try/catch blocks.

Using SETERR:

use java.lang.Integer

seterr java_err

rem This will throw a NumberFormatException
value = Integer.parseInt("not_a_number")
print "Value: ", value
release

java_err:
print "Error number: ", err
ex! = BBjAPI().getLastJavaException()
if ex! <> null() then
print "Java exception: ", ex!.getMessage()
print "Exception type: ", ex!.getClass().getName()
fi
release

Using ERR= on a single statement:

use java.lang.Integer

value = Integer.parseInt("not_a_number", err=parse_failed)
print "Parsed: ", value
release

parse_failed:
ex! = BBjAPI().getLastJavaException()
print "Parse failed: ", ex!.getMessage()
release

BBjAPI().getLastJavaException() returns the actual Java exception object, so you can call .getMessage(), .getClass().getName(), .getCause(), or any other Java exception method on it.

For the full error handling model including ERR=, SETERR, and error priority rules, see the Error Handling chapter.

Classpath Configuration

BBj's bundled classpath includes the standard JDK library and several third-party JARs (org.json, Gson, and more). When you need an external JAR beyond what BBj bundles:

  1. Open Enterprise Manager and navigate to Java Settings
  2. Add the JAR path to the classpath list (e.g., /opt/libs/my-library.jar)
  3. Restart BBjServices for the change to take effect
  4. Use the classes from that JAR in your BBj code:
use com.example.MyLibrary

obj! = new MyLibrary()
result! = obj!.doSomething()

The classpath change applies to all BBj programs running on that BBjServices instance. For per-program classpath control, you can also set the classpath in the program's configuration within Enterprise Manager.

Limitations Summary

LimitationDetails
No generics syntaxRaw types only -- HashMap, not HashMap<String, String>
Runtime type resolutionNo compile-time type checking for Java calls
Java exceptions become error 252Handle with ERR= or SETERR, inspect with getLastJavaException()
Object identity differencesComparing object identity across the BBj/Java boundary can produce unexpected results
Reading Legacy Code

See Reading Legacy Code for legacy Java interop patterns including pre-use fully-qualified names and ADDR()/CALL callbacks.

Further Reading