Search code examples
j2objc

How to set up Apache Commons Logger


Anyone knows how to setup Apache Commons Logger? It seems like people got it running, but I'm failing miserably.

My current setup is quite simple:

build.gradle:

compile('commons-logging:commons-logging:1.2')
j2objcTranslation 'commons-logging:commons-logging:1.2'

logger initialization:

private static Log logger = LogFactory.getLog(ApiService.class);

also have a quite simple logging.properties file, can attach if needed.

After translating and running on iOS emulator the following exception is thrown:

2016-09-21 19:39:35.960 temple8-ios[32544:598370] Fucking logger
2016-09-21 19:39:36.048 temple8-ios[32544:598370] *** Terminating app due to uncaught exception     'OrgApacheCommonsLoggingLogConfigurationException', reason:  'java.lang.ClassNotFoundException:  org.apache.commons.logging.impl.LogFactoryImpl (Caused by  java.lang.ClassNotFoundException:  org.apache.commons.logging.impl.LogFactoryImpl)'
 *** First throw call stack:
(
    0   CoreFoundation                      0x000000010e471d85     __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010d40cdeb objc_exception_throw + 48
    2   temple8-ios                         0x000000010c056a27 OrgApacheCommonsLoggingLogFactory_newFactoryWithNSString_withJavaLangClassLoader_withJavaLangClassLoader_ + 327
    3   temple8-ios                         0x000000010c059d06 OrgApacheCommonsLoggingLogFactory_getFactory + 3030
    4   temple8-ios                         0x000000010c056026 OrgApacheCommonsLoggingLogFactory_getLogWithIOSClass_ + 70

Edit 1

@tball provided some great details in his answer, but that lead to a new issue. I've added a static reference to LogFactoryImpl and included java.util.logging.IOSLogHandler in the project. When trying to translate that class the compiler throws the following error:

/java/util/logging/IOSLogHandler.m:58:17: error: method definition for 'IOS_LOG_MANAGER_DEFAULTS' not found [-Werror,-Wincomplete-implementation]
 @implementation JavaUtilLoggingIOSLogHandler
                ^
java/util/logging/IOSLogHandler.h:34:1: note: method    'IOS_LOG_MANAGER_DEFAULTS' declared here
+ (NSString *)IOS_LOG_MANAGER_DEFAULTS;
^
1 error generated.

I'm using the latest version of IOSLogHandler from the j2objC github repository and have posted the generated IOSLogHandler.m on gist.

Many thanks for all the help!


Solution

  • The linker isn't including org.apache.commons.logging.impl.LogFactoryImpl because it's dynamically loaded, and so there were no references to it that needed resolution during linking. I don't know how to fix this in Gradle, but there are two general solutions:

    1. Link with the -ObjC flag, which causes ALL Objective C classes in all static libraries to be linked into the app. However, this may pull in lots of unneeded classes, so check the app's before and after binary size to see if that's acceptable.

    2. In a class that is already linked into your app, add a reference to org.apache.commons.logging.impl.LogFactoryImpl. It can be as simple as:

      @SuppressWarnings("unused") private static final Class loggingImplClass = LogFactoryImpl.class;