How to include JAXB functions in AnyLogic 8.4.0? - java

I have an AnyLogic model that uses JAXB functions for parsing an XML file. The model used to work earlier but it doesn't now since apparently the newer versions of Java don't include JAXB. The online examples of how to do this in Java programs doesn't fit AnyLogic environment.
Based on online searches, I have downloaded and included the jaxb-api-2.4.0-b180830.0359.jar file in AnyLogic model. That by itself doesn't work and leads to the following error:
SEVERE: null
javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
I then added the following in the import section:
import java.xml.bind;
import com.sun.xml.bind;
Also tried:
import java.xml.bind.*;
import com.sun.xml.bind.*;
Both resulted in the same error:
The import com.sun.xml.bind cannot be resolved.
The import java.xml cannot be resolved.
On line guidance from for example https://www.dariawan.com/tutorials/java/using-jaxb-java-11/ recommend adding the dependencies using below code to Java programs:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb.api.version}</version>
</dependency>
How do we specify such dependencies via AnyLogic interface?
Once JAXB functions work, they should lead to parsing the data in XML file and creating and populating corresponding objects in AnyLogic as was the case before.

Sounds like you didn't add the .jar file properly in AnyLogic...
Click on your model in the projects view (the top-most entry above all agents and Main):
In the properties, you can add your .jar file under the "Dependencies" tab:
Do follow the advise to "keep a copy in your model folder" so it doesn't get lost.
Now you can import what you need and it will work (unless the .jar file is broken itself).
PS: Might be better to rephrase your question to "How to load an external jar file to my model dependencies"

The problem
As already stated in the question, the problem is this:
JAXB as a Java tool for XML treatment has been removed from the Java standard library beginnig with Java 9. The reason for this decision was to make the standard Java library more lightweight.
Dependencies in Java
This can be solved by including the removed package(s) manually into your project. As a lot of people already had this problem, quite an amount of SO questions for this exist, like this and this.
In these answers it is suggested to 'load dependecies', eg like this:
<!-- https://mvnrepository.com/artifact/pacakgename -->
<dependency>
<groupId>packagename</groupId>
<artifactId>modulename</artifactId>
<version>1.0.0</version>
</dependency>
These dependency statements are interpreted by the Java IDE such as Eclipse (with a package manager such as Maven), and the stated packages then get automatically loaded from an online package repository and included in the project.
In AnyLogic, the procedure is slightly different!
Dependencies in AnyLogic
In AnyLogic the exact same thing is happening when you click on your project in the AnyLogic editor, and add a JAR file under the Dependencies tab, see Benjamin's answer for this. In order to do that you will manually have to find the JAR file in a package repository and download it first.
Needed Pacakges
This is where I am not completely sure. I'll got an example to run when I included the following packages, but probably there is redundancy, so you might want to try around with variations of them:
javax.xml.bind / jaxb-api / 2.3.0-b170201.1204
javax.activation / activation / 1.1
org.glassfish.jaxb / jaxb-runtime / 2.3.0-b170127.1453
com.sun.xml.bind / jaxb-impl / 2.2.11
com.sun.xml.bind / jaxb-core / 2.2.11
Example
I created a simple example model in AnyLogic, that is based on this blog post. You can run and download it (including the dependeny Java packages) here.

Related

How to fix 'Package is declared in module, but module does not read it' error in IntelliJ JavaFX?

I've created a JavaFX project using IntelliJ, together with Maven. I'm trying to test some system that adds items into an XML file and then parses it and shows me all the items added to the file.
I want to use FasterXML/Jackson for parsing the files. In my pom.xml, I've added the following dependency:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.13.2</version>
</dependency>
(...) and I also loaded the Maven changes from the button provided by IntellJ. I also pressed the Reload all Maven Changes button. The "Dependencies" folder seems to be all okay. I've received no errors or complaints:
However, when I'm trying to import some Jackson-related class, such as ObjectMapper, like this:
import com.fasterxml.jackson.databind.ObjectMapper;
(...) I receive such an error:
Package 'com.fasterxml.jackson.databind' is declared in module 'com.fasterxml.jackson.databind', but module 'com.example.demo1' does not read it.
This is my project structure:
What could be the problem?
I've managed to fix my problem. In my module-info.java I needed to add the following line of code:
requires com.fasterxml.jackson.databind;
Found something similar in an answer provided to a question on Stack (How to solve package is declared in module, but module does not read it?), although the user who answered said you need to also open the module.
Opening the module, though, would result in some other error, but just mentioning it as a requirement should be enough.

Using Jsoup library on eclipse [duplicate]

I have just recently started using Eclipse and am running into problems trying to install external libraries. Following online tutorials, I add the .jar file to the classpath and I see it in the referenced libraries folder. Despite this, when trying to import, I get the error:
The package org.apache.commons is not accessible
For reference, I am trying to install the apache math commons library.
Your code probably has two issues.
First, the import statement is wrong since in Java you cannot add a package itself, but all classes of a package as follows (note .*; at the end):
import org.apache.commons.math4.linear.*;
or a specific class, e.g.
import org.apache.commons.math4.linear.FieldMatrix;
Second, you use the Java Platform Module System (JPMS) by having a module-info.java file in the default package probably without the required requires <module>; statement. JPMS was introduced in Java 9 and you have Java 12.
Do one of the following:
Delete the module-info.java file (if needed, you can recreate it via right-clicking the project folder and choosing Configure > Create module-info.java)
In module-info.java add the corresponding requires statement, e.g. by going to the line with the import statement and using the corresponding Quick Fix (Ctrl+1)

Generate XSD from XML programmatically in Java

I'm looking for a leightweight library that allows me to genereate an XSD from XML in Java (no commandline tool). I know that it is not a clean way to generate it, but in this case I need to do it. Also the XML is very simple in terms of structure.
I already looked into Trang, but there is no API documentation except how to call it from command line.
Also I checked out xsd-gen, but the issue with that library is that one would need to modify some package declrations in the source code which I couldn't find.
Any other suggestions?
I am the author of the tool xsd-gen. I converted the tool to be a library as well, and uploaded the artifact to Maven Central:
<dependency>
<groupId>org.wiztools</groupId>
<artifactId>xsd-gen</artifactId>
<version>0.2.1</version>
</dependency>
Now it is simple to use as a library within your application:
import org.wiztools.xsdgen.XsdGen;
import java.io.File;
import java.io.FileOutputStream;
...
XsdGen gen = new XsdGen();
gen.parse(new File("in.xml"));
File out = new File("out.xsd");
gen.write(new FileOutputStream(out));
I included the xsd-gen source code and it worked for me. You only need
TypeInferenceUtil.java
XsdGen.java
The package declarations I used (for Gradle) were:
compile("com.io7m.xom:xom:1.2.10")
compile("org.wiztools.commons:wiztools-commons-lib:0.4.1")

java / NoClassDefFoundError error at runtime only

I'm having trouble including a JAR file that adds a class that will let my main class send emails.
What I have done...
Saved the EmailAPI.jar file in my folder, as mentioned in below POM text (and it finds it, because in NetBeans I can explore the class)
Updated the dependency in my POM file, as follows:
<dependency>
<groupId>EmailAPI</groupId>
<artifactId>EmailAPI</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}\src\lib\EmailAPI.jar</systemPath>
</dependency>
Add the import (NetBeans automatically added this when I used the Email class, so it seems to know where to look...)
import me.nrubin29.emailapi.Email;
Call the class, directly using the structure provided
//send an email
new Email()
.withSMTPServer("smtp.gmail.com")
.withUsername("xxxxx#gmail.com")
.withPassword("xxxxxxx")
.withTo("xxxxx#gmail.com; xxxxx#gmail.com")
.withSubject("[RP] Server has started")
.withBody("This is the body!")
.send();
I can build fine, it all works out... but then when I try to run it (as a plugin to Minecraft), I get a NoClassDefFoundError, as shown here:
http://pastebin.com/V33gCLVG
I don't understand what I'm missing here. Can anyone point me in the right direction?
You use <scope>system</scope>. Is it available in the Minecraft enviroment? See Maven, Introduction to the Dependency Mechanism, Dependency Scope: "This scope is similar to provided [...] " and under provided: "indicates you expect [...] a container to provide the dependency at runtime."
It means that you are missing the jar in your runtime environment. You might need to change the scope of your maven dependency to compile.
EmailAPI requires two JARs in order to run. I think they are activation and mail or something. I can look at the project but I think you might be missing them.

Using MessagePack with Android

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.** { *; }

Categories