Has someone tried to use MessagePack with an Android app?
Is it possible? I have tried to use the Jar from msgpack-java and received the following Exception:
Caused by: java.lang.ExceptionInInitializerError
at org.msgpack.Packer.pack(Packer.java:532)
at org.msgpack.MessagePack.pack(MessagePack.java:31)
... 15 more
Caused by: java.lang.ExceptionInInitializerError
at org.msgpack.template.TemplateRegistry.<clinit>(TemplateRegistry.java:38)
... 17 more
Caused by: java.lang.VerifyError: org.msgpack.template.BeansFieldEntryReader
at org.msgpack.template.builder.BeansTemplateBuilder.<init (BeansTemplateBuilder.java:42)
at org.msgpack.template.builder.BuilderSelectorRegistry.initForJava(BuilderSelectorRegistry.java:73)
at org.msgpack.template.builder.BuilderSelectorRegistry.<clinit>(BuilderSelectorRegistry.java:38)
... 18 more
The code that I use is very simple
PrintWriter out = new PrintWriter(socket.getOutputStream());
Message msg = new Message();
msg.body = "asdasdasd";
msg.from = "qwe";
msg.to = "ttt";
byte[] bytes = MessagePack.pack(msg);
out.print(bytes);
out.flush();
I have javassist.jar, msgpack-0.5.2.jar, slf4j-api-1.6.2.jar and slf4j-jdk14-1.6.2.jar in my lib directory.
In my server application this code works fine with the same libraries.
(Hopefully) FINAL UPDATE
msgpack : 0.6.8 works on Android without any problems
msgpack-rpc : 0.7.0 works on Android with one caveat.
Specifically, you need to add the following to onCreate for API Level 8 (Android 2.2.1), and possibly lower:
java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");
due to this bug.
If you want to see a simple example, here's a pair of projects set up for this purpose:
https://github.com/mikkoz/msgpack-android-test-server/tree/master/msgpack-android-test-server
https://github.com/mikkoz/msgpack-android-test-client/tree/master/msgpack-android-test-client
Previous Versions
UPDATE: as of 0.6.7 msgpack should be compatible with Android (there is a small dependency exclusion issue). Check the text below for msgpack-rpc (which also might be adapted in the future).
NOTE: If you're also using msgpack-rpc, you need to do the following steps:
Download the msgpack-rpc source from git://github.com/msgpack/msgpack-rpc.git (specifically, the "java" folder).
Change the main msgpack artifact version to the one you've built.
In org.msgpack.rpc.loop.netty.NettyEventLoop, change the NioClientSocketChannelFactory to OioClientSocketChannelFactory(getWorkerExecutor()).
Build the MessagePack-RPC in the same way as in the case of the main MessagePack JAR (see Step 11 above).
The NettyEventLoop replacement is due to this issue:
http://markmail.org/message/ypa3nrr64kzsyfsa .
Important: I've only tested synchronous communication. Asynchronous might not work.
And here's the reason for msgpack not working with Android prior to 0.6.7:
The reason for the error is that MessagePack uses several java.beans classes that are not included in the Android SDK. You're probably using the MessagePackBeans annotation.
This is a similar problem to the one described here, for which the general solution is outlined here. Unfortunately, in our case it requires a rebuild of msgpack. Here's what I did (you can almost certainly skip Steps 5 and 8, but I haven't tried it that way) :
Download the MessagePack source from https://github.com/msgpack/msgpack-java.git.
Import the MessagePack source as a project in your IDE.
Download the Apache Harmony source for the relevant packages from http://svn.apache.org/repos/asf/harmony/enhanced/java/trunk/classlib/modules/beans/src/main/java .
Copy these packages into your MessagePack project's src/main/java folder:
java.beans
java.beans.beancontext
org.apache.harmony.beans
org.apache.harmony.beans.internal.nls
In your MessagePack project, remove the following classes:
PropertyChangeListener
IndexedPropertyChangeEvent
PropertyChangeEvent
PropertyChangeListenerProxy
PropertyChangeSupport
Rename the java.beans packages to something different, e.g. custom.beans .
Change all java.beans references to the renamed ID, so again e.g. custom.beans. This applies especially to BeansFieldEntryReader (this class is the reason for the original error).
Change the custom.beans references for the five classes you removed in Step 5 back to java.beans.
In the org.apache.harmony.beans.internal.nls.Messages class, comment out the method setLocale, and remove the imports associated with it.
Remove all classes that still have errors, except Encoder. In that class, comment out all references to the classes you've removed. You should now have an error-free project.
Build the MessagePack JAR:
If you're using Maven, change the version in the pom.xml to something unique, run Maven build with the install goal, then add the dependency in your Android project with that version.
If you're not using Maven, you have to run the jar goal for Ant with the included build.xml. Replace the msgpack JAR in your Android project with this one.
If you're publishing your app, remember to include the relevant legal notice for Apache Harmony. It's an Apache License, just like MessagePack.
That should do it. Using your example code, and my own data class, I was successfully able to pack and unpack data.
The entire renaming ritual is due to the fact that the DEX compiler complains about java.* package naming.
There is a critical msgpack bug saying data packed with msgpack will get corrupted on the Dalvik VM. http://jira.msgpack.org/browse/MSGPACK-51
There is an ongoing effort by #TheTerribleSwiftTomato and the MessagePack core team to get MessagePack working on Android, please see the related GitHub issue. The fix mentioned in #TheTerribleSwiftTomato's answer is to be found here.
Update
I've managed to get it at least running on Android by (painstakingly) adding all the necessary javassist Classes which are currently required for the build to succeed. An extra 600KB gain in size, yet at least it seems to work. All in all, it appears to be working to some extent on Android, eventually check out the lesser-known resources about Message Pack such as its User Group and its Wiki for more information.
On a side-note, be sure to use a HTTP Request Library (such as LoopJ's Android Async HTTP or Apache's HttpClient) which can handle binary data.
Last but not least you can ping me if there is interest in this jar which makes MessagePack seemingly work on Android – credits go out of course to #TheTerribleSwiftTomato who supplied the fix above!
I suggest you write this in the main proguard-rules file-
-dontwarn org.msgpack.**
-keep class org.msgpack.** { *; }
Related
Recently I've been working on report generation with Jasper. I have created a simple program to test it and when running it via IDE it did work fine.
Then I moved the (very short) class to WildFly sever application and despite having the exact same code and library generation fails with cannot find symbol. Those symbols it cannot find are JREvaluator, JRFillVariable as well as packages such as net.sf.jasperreports.engine
In so far I have confirmed that:
Project builds (meaning those classes are visible for javac, but not jvm)
jasperreports-6.13.0.jar is added to war (it's present in /WEB-INF/lib folder alongside other libraries, like gson and hibernate
jasperreports-6.13.0.jar contains the missing classes
It looks to me like the problem doesn't lie in library not being loaded or missing classes (because in testing environment it works), but like something was preventing JBoss class loader from loading those classes
Attempted (and failed) solutions
Clean and Build
Adding -Djava.awt.headless=true to VM options - this did not changed anything
Adding -Djava.awt.headless=false to VM options - also didn't change a thing, but once caused NullPointerException inside jasperreport library. For testing program - worked in both cases
Adding commons-beanutils-1.9.4.jar, commons-digester-2.1.jar, commons-collections4-4.4.jar and commons-loggin-1.2.jar - with no changes
Adding jasper-compiler-jdt-5.5.23.jar - this caused a different error, namely NoSuchMethodError for org.eclipse.jdt.internal.compiler.ICompilerRequestor and few others. This library however should not be necessary as - from what I understand - jasperreport-6.13.0.jar already contains it's compiler and separate library for compiler is not required since a long time.
What has not been attempted:
Forcing the classes to load (http://www.java2s.com/Code/Java/Reflection/Forcethegivenclasstobeloadedfully.htm)
Dynamically loading jar during Runtime or using custom class loader
Update: after looking at this answer and applying the suggestion the missing class was different. Which suggests that the dependencies inside jasperreport.jar are not being loaded properly
I have figured it out
For some reason in server project libraries used by jasperreport.jar were not loaded, but in the testing project they were (might be due to WildFly, might be due to differences between IntelliJ and NetBeans)
Here is the list of libraries, based on pom.xml file in jasperreport.jar that I have added. Some might not be necessary and the list might not be exhaustive (I basically stopped adding libraries once report started generating) but it's good enough base if someone else runs into this problem:
commons-beanutils-1.9.4.jar
itext-2.1.7.jar
poi-ooxml-4.1.1.jar
commons-collections4-4.4.jar
jcommon-1.0.23.jar
xalan-2.7.2.jar
commons-digester-2.1.jar
jfreechart-1.0.19.jar
xmpcore-5.1.3.jar
commons-logging-1.2.jar
poi-4.1.1.jar
In JDeveloper 12c, I have created a BPM application/project. Project SOA Settings are Composite With Business Rule.
The project has a Mediator and is exposed as a REST service. I am deploying using the IntegratedWebLogicServer
The XML Facts are rather generic including lists of fields, sub-lists, and sub-sub-lists, etc. This makes navigating the inputs more challenging.
I created a Java class with some static methods that more easily retrieve the data based on an expression. I created a jar with that class and then imported the class into the Java Facts. I then created rules that call the static methods on that Java Fact.
The rules validate just fine and I can now successfully run the rules from the "Test" tab of the rules. I get expected results. However, when I deploy the project it seems like the imported jar is not deployed along with it since I get the following exception:
oracle.rules.rl.exceptions.UndefinedException: The symbol "mypackage.MyUtil" is undefined.
at line 22 column 14 in /Ruleset(main)
I thought that importing the class in the Java Facts would cause my custom jar or at least the class that I imported to be deployed. But it seems that this may not be the case. Am I missing something? Is there somewhere in my project that I can place the jar to cause it to be deployed?
I tried adding the jar to the Libraries and Classpath entries of the project. I also tried adding it to a user library located in the project and adding that to the Libraries and Classpath list. But both had no effect.
I am new to JDeveloper and Oracle BPM, so I'm hoping there's something simple I'm missing here.
The solution was to add the jar to this directory:
MyBpmApplication\MyBpmProject\SOA\SCA-INF\lib
I had to include some bittorrent java library to my Android project. My workspace: Android Studio 1.0.2 (osx) and jdk8. I've connected its maven-repository (ttorrent:1.4) with Gradle and after starting using main classes and features i've got an error:
java.lang.NoSuchMethodError: No static method encodeHex([BZ)[C in class Lorg/apache/commons/codec/binary/Hex; or its super classes (declaration of 'org.apache.commons.codec.binary.Hex' appears in /system/framework/ext.jar).
I went to library's code and find out that it's using org.apache.commons.codec from where ttorrent is importing encodeHex and calling it. Looks like binaryHex method is gone! Or it never been. But I went to commons.codec's code and found binaryHex in its place and with arguments that I was looking for. How come? Why? My Android Studio found it. But java runtime not.
In fact, the decision was more difficult than I thought. Let's start with the fact that I came across an article by Dieser Beitrag'a, from which it is clear that not one I had similar problems. The whole thing turned out that within the Android operating system already has some libraries that have a higher priority use, rather than loaded with dependencies along with the application. Among them there and my org.apache.commons.codec.
Yes, such things.
To solve the problem in two ways, either you need to pump source code library and using some tool to rename the project (i.e. org.apache.commons.codec to org.apache.commons.codec.android), collected it to a .jar file, include .jar in a project and at code use imports of the necessary classes only "our" library, or just get the required class to your project and do not pull a megabytes of unneeded code. However, I did just that.
Thanks for help!
I received this error:
NoClassDefFoundError: org/apache/commons/collections/IteratorUtils
I have downloaded the newest jar: commons-collections4-4.0.jar
And it looks like multiple libs/apps are looking for commons/collections (not commons/collections4). I am trying to use display tags and get this problem.
Where can I find commons-collections.jar?
Commons-collections is an Apache utility - you could try looking at Apache (http://commons.apache.org) or Maven Central (http://search.maven.org).
I must confess I am not familiar with commons-collections4. However, I would imagine you need to read the JavaDocs and/or release notes to see if any method signatures have changed and upgrade your method calls accordingly. From your error messages, the package names at the very least are different.
We are developing a fairly large project and have many dependencies. Recently, we ran into an issue with a conflict between two of them, agileAPI.jar and axis.jar. Both are 3rd party libraries.
The code in question depends directly on agileAPI.jar. If I build it with just that in the build path, everything that depends on it works correctly.
As soon as I add axis.jar to the build path (just adding it, not writing code that depends on it), everything goes wrong. Some of the code that depended on the first library is now throwing exceptions from the 2nd library. It is as if the first library is picking and choosing methods to call from the 2nd library, instead of whereever it was calling them from prior.
I have code in the project that needs axis.jar directly, so I can't just remove it from the build path. I need to find a way to have these two exist in the same build path, but ignore each other.
It should be noted that both libraries coexisted prior to a recent upgrade with agile. I have been working with Oracle's support team to try and resolve this. After two weeks, though, I am looking for other sources of help.
Our environment is Windows and Eclipse, although in testing this, it also occurs when running java from a command line. Our JDK is 1.5.0_22.
Any help would be appreciated.
Thank you,
David
EDIT:
As requested, here are the stack traces that we see. The first stack trace is printed in the code beyond my control:
java.lang.NoSuchMethodError: org.apache.axis.description.OperationDesc.setStyle(Lorg/apache/axis/constants/Style;)V
at com.agile.webfs.components.fileserver.client.FileServerSoapBindingStub._initOperationDesc1(FileServerSoapBindingStub.java:37)
at com.agile.webfs.components.fileserver.client.FileServerSoapBindingStub.<clinit>(FileServerSoapBindingStub.java:20)
at com.agile.webfs.components.fileserver.client.FileServerWSServiceLocator.getFileServer(FileServerWSServiceLocator.java:43)
at com.agile.webfs.client.IFSLocator.getRemoteFileServer(IFSLocator.java:128)
at com.agile.webfs.client.IFSLocator.getConnection(IFSLocator.java:101)
at com.agile.api.pc.EJBLookup.createFileSession(EJBLookup.java:444)
at com.agile.api.pc.EJBLookup.getFileSession(EJBLookup.java:432)
at com.agile.api.pc.attachment.IFSOutputStream.getFileSession(IFSOutputStream.java:133)
at com.agile.api.pc.attachment.IFSOutputStream.copyFrom(IFSOutputStream.java:87)
at com.agile.api.pc.attachment.IFSOutputStream.copyFrom(IFSOutputStream.java:115)
at com.agile.api.pc.TableAttachment.uploadFile(TableAttachment.java:886)
at com.agile.api.pc.TableAttachment$AddFiles2Action.doSdkAction(TableAttachment.java:724)
at com.agile.api.common.SDKAction.run(SDKAction.java:23)
at com.agile.api.common.OracleAuthenticator.doAs(OracleAuthenticator.java:131)
at com.agile.api.common.Security.doAs(Security.java:54)
at com.agile.api.common.Security.doAs(Security.java:109)
at com.agile.api.pc.TableAttachment.addFiles2(TableAttachment.java:483)
at com.agile.api.pc.TableAttachment.createNewBlob2(TableAttachment.java:459)
at com.agile.api.pc.TableAttachment.doCreateServerRowWithParam(TableAttachment.java:363)
at com.agile.api.pc.Table.createTableRow(Table.java:238)
at com.agile.api.pc.TableAttachment.createTableRow(TableAttachment.java:169)
at com.agile.api.pc.Table.createRow(Table.java:202)
at com.[snip].updateAttachments(VaultImportService.java:3068)
at com.[snip].processIncorporatedFile(VaultImportService.java:926)
at com.[snip].processPdxFile(VaultImportService.java:532)
at com.[snip].processPdxRequest(VaultImportService.java:388)
at com.[snip].<init>(VaultImportService.java:299)
at com.[snip].main(VaultImportService.java:3660)
After the exception bubbles up and we catch it, the stacktrace that we print looks like:
at com.agile.api.pc.Session.createError(Session.java:1772)
at com.agile.api.pc.EJBLookup.createFileSession(EJBLookup.java:454)
at com.agile.api.pc.EJBLookup.getFileSession(EJBLookup.java:432)
at com.agile.api.pc.attachment.IFSOutputStream.getFileSession(IFSOutputStream.java:133)
at com.agile.api.pc.attachment.IFSOutputStream.copyFrom(IFSOutputStream.java:87)
at com.agile.api.pc.attachment.IFSOutputStream.copyFrom(IFSOutputStream.java:115)
at com.agile.api.pc.TableAttachment.uploadFile(TableAttachment.java:886)
at com.agile.api.pc.TableAttachment$AddFiles2Action.doSdkAction(TableAttachment.java:724)
at com.agile.api.common.SDKAction.run(SDKAction.java:23)
at com.agile.api.common.OracleAuthenticator.doAs(OracleAuthenticator.java:131)
at com.agile.api.common.Security.doAs(Security.java:54)
at com.agile.api.common.Security.doAs(Security.java:109)
at com.agile.api.pc.TableAttachment.addFiles2(TableAttachment.java:483)
at com.agile.api.pc.TableAttachment.createNewBlob2(TableAttachment.java:459)
at com.agile.api.pc.TableAttachment.doCreateServerRowWithParam(TableAttachment.java:363)
at com.agile.api.pc.Table.createTableRow(Table.java:238)
at com.agile.api.pc.TableAttachment.createTableRow(TableAttachment.java:169)
at com.agile.api.pc.Table.createRow(Table.java:202)
at com.[snip].updateAttachments(VaultImportService.java:3068)
at com.[snip].processIncorporatedFile(VaultImportService.java:926)
at com.[snip].processPdxFile(VaultImportService.java:532)
at com.[snip].processPdxRequest(VaultImportService.java:388)
at com.[snip].<init>(VaultImportService.java:299)
at com.[snip].main(VaultImportService.java:3660)
In both cases, the line "at com.agile.api.pc.Table.createRow(Table.java:202)" is the agileAPI call that I am making. I have removed our package structure, as it identifies the company that I work for. They value privacy and security.
I'd advise you to check these two things first:
Open the axis.jar file with some zip utility, like 7-Zip or WinRar. See if there's a folder called "services" in the META-INF folder in the jar. If there is, it's possible that the axis.jar file specifies implementations for specific interfaces that somehow don't interoperate with agileAPI. Also do the same for agileAPI.jar, since it might itself declare an interface implementation that axis doesn't like.
Open both agileAPI.jar and axis.jar with a zip utility, then check if there's packages with the same name. If there's none, it won't be a naming conflict. If there's one or more, open the corresponding folders and do the same check recursively. If you end up with at least one class with the same name in the same package across the two jars, it's probably a naming conflict.
That should catch the most obvious issues. If none of this is the case, we'll need to look deeper.
A way to solve such classpath issues is to use a module system such as OSGi or the NetBeans Platform module system where each module has its own classloader.