Skip to main content

Posts

Mapping tests from TestNG to JUnit

In the summer of 2020, J2ObjC's JRE emulation library (a fork of Android's libcore library ) was updated from Android Nougat to Android 10. The update consisted of adding new APIs, and updating the existing code. Apart from general functionality changes, one of the main goals of the update was to port new test cases to better verify that the JRE emulation library works correctly. While updating the java.time package, I came across a tck.java.time package containing approximately 15,000 new test cases written in TestNG. The problem? J2ObjC only supports JUnit. Instead of supporting both TestNG and JUnit, we decided to build testng2junit , a tool that converts TestNG tests to JUnit. How Can These Frame works be Mapped? To convert from TestNG to JUnit, we needed to determine where the two testing frameworks differed. Attempting to run the TestNG tests through the compiler gave us plenty of compile-time errors to sift through. These syntax errors, coupled with documentation from
Recent posts

Catching Java exceptions in Swift via j2objc

TL;DR : it’s possible to handle Java-originating exceptions in Swift for j2objc -based projects. Scroll to the end for example code. It’s getting more common to call j2objc -generated Objective-C code from Swift as iOS development shifts to this modern language. At a high level, we can imagine this means calling Java code from Swift. But Objective-C is an important link in this chain and it shapes the way Swift interacts with the code that started its life as Java. j2objc  does a great job of supporting Swift’s features when called with the --swift-friendly  flag. This feature is particularly useful when the Java code is annotated with @Nonnull , @Nullable , and @ParametersAreNonnullByDefault  to enforce Swift’s optionality at compile time and as you type in Xcode. But there’s one important Java feature that gets lost in translation on the way to Swift: exceptions. You might expect to catch Java exceptions from Swift like: do {     // original Java code throw

Breaking Retain Cycles with @Weak and Other Techniques

The runtime on iOS and macOS uses reference counting to manage memory. When two objects make strong references to each other, a retain cycle is formed. Consider a Document object that has a Header. The Document owns the Header, but often the Header is also modeled to have a document (or “parent”) field:

Default Methods

We are pleased to announce the support for Java 8 default methods in J2ObjC. The compiler also translates static methods in interfaces now. Together they make Java interfaces more useful, and, when combined with lambdas, enable a wide range of new idioms and programming styles. To translate this new language feature, pass the command line argument -source 8 to j2objc . The Java Tutorials has a good introduction to default and static methods in interfaces. Another good introduction is Richard Warburton's Java 8 Lambdas . Here we give three short examples to show why this language feature is useful. Providing New Features that Build Upon Essential Methods Default methods enable us to keep the requirements of an interface minimal while still providing good default implementations that build upon those essential methods. Imagine you have an interface for objects (for example, appliances) whose date and time can be set: interface DateTimeSettable { void setDate ( int y

Lambdas in Java 8 - (Dys)functional Interfaces

1970 - Guy Steele and Gerald Sussman create Scheme. Their work leads to a series of "Lambda the Ultimate" papers culminating in "Lambda the Ultimate Kitchen Utensil." This paper becomes the basis for a long running, but ultimately unsuccessful run of late night infomercials. Lambdas are relegated to relative obscurity until Java makes them popular by not having them. James Iry A Brief, Incomplete, and Mostly Wrong History of Programming Languages So we finally have lambda expressions in Java with Java 8. Well, actually we have had them for a year now, and companies and universities have started upgrading at a snail’s pace. Some from Java 6 to Java 7, but let’s ignore that for now and instead talk about lambdas, implementation details, and how this all impacts j2objc and you. Before we talk about lambdas we have to talk about functional interfaces, and after we talk about functional interfaces we will need to mitigate confusion with history, wi

Protocol Buffers!

Protocol Buffers are Google’s preferred method of representing and communicating structured data. For most Google projects, protocol buffers are used for data storage or client-server communication. As such, a working protocol buffer solution has been a requirement for J2ObjC from day one. Until recently our solution contained internal dependencies that prevented it’s public release, but now I am very pleased to be able to make our internal solution available to all J2ObjC users. Let’s take a quick look at how protocol buffers are used (for a more in-depth look you can read through the Protocol Buffers Developer Guide ). Suppose my app needs a geographic location, so I would create a geo.proto file with the following declaration: message Location {   optional string name = 1;   optional double latitude = 2;   optional double longitude = 3; } Then I can use the protocol buffer compiler, “protoc”, to generate data types in the languages I need: $ protoc --java_out=src/java --cpp_ou