Java class not loading from javaclassloader service in IIB - java

I have an application build in IIB v10 where i am referencing a java routine from esql. I have created the java class as an independent resource, then exported it as a JAR file and placed it in a folder under C://lib. There was an existing configuration service for java class loader which also pick yet another jar file from C://lib. I then amended the existing configuration service for Java Class loader with the new jar name and its path. Also, did a restart of the broker and inspected via mqsireportbroker command and webconsole to confirm the new jar has been updated in the configuration service. Now when i deploy the BAR file to the server, I am getting the below error.
BIP3202E: (com.xxxx.soa.xx.xxx.createMD5Hash, 1.12) : An error occurred when trying to resolve the Java class or method 'com.xxxx.gen.createMD5.createMD5Hash' which is referred to by the routine 'createMD5Hash'.
Further messages are generated that explain the error in more detail.
Correct the syntax of your Java expression in node 'com.xxxx.soa.xx.xxx.createMD5Hash', around line and column '1.12', then redeploy the message flow.
BIP2943E: The Java Method 'com.xxxx.gen.createMD5.createMD5Hash' could not be found as its containing class could not be found in the deployed bar file or in the 'workpath/shared-classes/' directory.
The specified Java Method 'com.xxxx.gen.createMD5.createMD5Hash' belongs to a class that could not be found in the deployed bar file or the 'workpath/shared-classes/' directory. Ensure that the fully qualified name of the method is correct and that its containing class or jar file is in the deployed bar file or in the 'workpath/shared-classes/' directory.
Examine and correct the SQL program.
When I put the jar file under workpath/shared-classes directorey, its working. But I want the jar file to take from the shared class librarry which is C://lib. What am I missing in this case?

All you need to do it to put your jar in the shared-classes folder.
You can find all the information about it in the IBM documentation really easily, but here is an example on Unix :
/var/mqsi/config/MY_BROKER/shared-classes
You can either put the .jar there, and it will be loaded for each execution group (also called integration servers).
If you know you only need this for a specific execution group, then you can copy it there :
/var/mqsi/config/MY_BROKER/MY_EG/shared-classes
And I would highly recommand you to use the second option, otherwise you might have performance issues if you do this with a lot of libraries

There are only a few paths where the .jar files are loaded from.
See for more information: https://www.ibm.com/support/knowledgecenter/en/SSMKHH_9.0.0/com.ibm.etools.mft.doc/bk58210_.htm
JAR files are loaded in the following precedence order:
JAR files placed in the integration server shared-classes directory allow only a single defined integration server to access them. Files placed in here are loaded first.
JAR files placed in the broker shared-classes directory allow only a single defined broker to access them. Files placed in here are loaded after any files placed in the integration server shared-classes directory.
JAR files placed in the top level shared-classes directory are made available to all brokers and all integration servers. Files placed in here are loaded after any files placed in the broker shared-classes directory.

I found it on windows here C:\ProgramData\IBM\MQSI\config*\shared-classes
using this command mqsireportbroker <my_broker_name>

Related

Running a Java Web Start application without Java Web Start

I want to run a fat client delivered as a Java web start application without Java web start. I launched it via javaws and managed to get all the jar files mentioned in the JNLP file from the cache after they were downloaded.
I tried running the jar file that contains the main class according to the JNLP file, but I get the 'Could not find or load main class' error. Were I just trying to run a class I'd set the classpath accordingly, but since I'm running a jar file with java -jar, as far as I know the classpath settings will be ignored anyway. Now I'm not sure what to do, does anybody know how to tackle this?
I'll answer this myself now, turns out it is stupidly simple: Get all the jar files, unzip them to get the content, merge all the content (best done with rsync), create a new MANIFEST.MF file that contains the main class to be loaded and the merged hashes for all existing files from all MANIFEST.MF files, zip again to create a jar. That's it.

Java resource not found in Jar, in web app in Tomcat 8

I have a web app running in Tomcat 8 and this web app war files includes several jars (through Spring framework). One of them is a jar called connector.jar. This connector.jar contains a method that receives a package name, and the method checks if a certain file is present. I am sure the file is present (triple checked it, also in the jar file), so in development, when running as exploded jar, it returns true, but when it's packaged in a jar and deployed as a war in Tomcat, it returns false.
Please help me understand what the problem can be, and how to solve this or debug it?
The method:
public boolean isPresent(String packageName) {
return getClass().getClassLoader().getResource(packageName + "index.json") != null;
}
Notes:
Example of the package name: "com/bla/connector/" (the package name
doesn't contain a leading "/").
I also used class.getResource(), but same result. In SO the advised
not to use this when finding a resource in a jar, as you might use
the wrong class loader. I am using ActiveMQ embedded in the same war.
The code can be called by a Queue Consumer. But I don't think that is
a problem the way I am using the ClassLoader.
UPDATE, some more details as requested:
I use maven as build tool (latest version), and maven builds the war. I use the default maven war layout. WEB-INF/classes, WEB-INF/lib. The lib folder contains all the jar, and the connector.jar.
The method isPresent is located in the connector.jar in the class com.company.HtmlWorker.
The files index.json is located in the package: com.company.json.account.
Output of the isPresent method when logging the created index.json name: "com/company/json/account/index.json"

Issues launching a JAR file from an executable JAR using Manifest file ClassNotFoundException

I have a project which uses both RMI and JDBC and I need to make it an executable JAR. Now my instructions are to make one JAR file with all my source code which ive included all my .java files. My second JAR needs to be the RMI server .class files and then the third JAR is to have all my RMI client .class files.
Now the first JAR and the third JAR I can make no problem but the issue lies with that in my second I require the use of JDBC so I need to include the mysql-connector-java-5.1.31-bin.jar file in it.
My folder consists of the following layout, only default packages are used and everything is in the root directory.
1st JAR - Source Code Jar File Contains...
A2Interface.java
A2InterfaceImpl.java
A2RmiClient.java
A2RmiServer.java
InvalidLocationException.java
DuplicatedAddressException.java
I used this command to jar it
jar cvf source.jar *.java
2nd JAR - Contains the classes related to RMI server, I also need the mysql JDBC jar file included along with it
And I used this command to JAR it
jar cvfm RMIserver.jar server.txt A2RmiServer.class A2Interface.class
A2InterfaceImpl.class *Exception.class mysql-connector-java-5.1.31-bin.jar
My server.txt Manifest file contains the following
Main-Class: A2RmiServer
Class-Path: mysql-connector-java-5.1.31-bin.jar
-empty line as per the docs-
3rd JAR - Contains the classes related to the RMI client
jar cvfm RMIclient.jar client.txt A2RmiClient.class
A2RmiClient$EventHandler.class
Any my client.txt manifest file contains
Main-Class: A2RmiClient
-empty line as per the docs-
Now everything jars perfect fine and I extract my first JAR file containing all my .java files with no errors. I then attempt to run my RMIserver.jar file with the following command...
First I start the registry..
start rmiregistry 5566
Then I run the executable jar file..
java -cp mysql-connector-java-5.1.31-bin.jar -jar RMIserver.jar
AND here is where I get an Exception of the following
Trouble: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: A2Interface
I cannot determine why this is doing this at all. If I dont use any jar files my code runs perfectly fine with ZERO exceptions but as soon as I try this I always get exceptions. I have searched many places and some people say that you cant include the mysql JAR file (or any JAR file) like this and even according to the Java doc here http://docs.oracle.com/javase/tutorial/deployment/jar/downman.html
They also mention that its designed for use only for JAR's over the network and not in the same directory, however my professor believes this can be done. I have been trying to figure this out for hours and have come to a wall. I don't know how I can make it work with using the necessary mysql JAR file.
OH and please dont mention using any other tools to create a JAR package as I cannot do that for my assignment or even eclipse. I can only do this from using strictly command line tools.
The ClassNotFoundException is happening in the rmiregistry, and it's being returned to your server application wrapped in a ServerException.
In normal usage, the RMI server annotates the classes with their codebase URL so that other Java processes can load the unknown classes. However, the jar file isn't a usable URL for this purpose (I'm not totally sure, but I think it's because it's generally insecure to load from file: URLs received from the network).
The reason it works when you're not using jar files is because the rmiregistry is able to find the missing classes in its own classpath (because you're running it in the same directory that contains A2Interface.class).
You have two choices:
Serve the class files (or a jar containing them) from an http server running on the RMI server's host, and use the java flag -Djava.rmi.server.codebase=http:... to point to the directory/jar where the classes can be found; or
Insert the common classes in every classpath: server, client, and rmiregistry.
For more detail, see http://docs.oracle.com/javase/7/docs/technotes/guides/rmi/codebase.html.
And here is where I get an Exception of the following
The Registry doesn't have that class available on its CLASSPATH. There are three solutions, in increasing order of difficulty:
Run the Registry inside the server JVM, via LocateRegistry.createRegistry(). When you do this, you must store the result of that call in a static variable, to prevent it being garbage-collected. That also makes it possible to unexport the Registry when you want the JVM to exit.
Run the rmiregistry with an appopriate CLASSPATH. There are several ways to do that, including -J-classpath and setting a CLASSPATH environment variable.
Use the RMI codebase feature.
Now my instructions are to make one JAR file with all my source code which ive included all my .java files. My second JAR needs to be the RMI server .class files and then the third JAR is to have all my RMI client .class files.
Your instructions are incorrect. You need to make four JAR files:
Source code (why?)
.class files that are common to both client and server
.class files that are only used on the server
.class files that are only used on the client.
(3) and (4) need manifests, both to name the Main-Class and to name (2) on the Class-path.
The server deployment needs (2) and (3). The client deployment needs (2) and (4).

Classpath in a Java Web Start application

I need to load an .xml file in META-INF, it works when the application isn't sandboxed, but in Java Web Start a different classloader (which is more restricted) seems to be used, so the file found in myproj.jar/META-INF/myfile.xml isn't loaded. It however works if I put the file in the current directory of the loading class (I put it under com/blabla/myproj/whatever/META-INF/myfile.xml).
I couldn't find any classpath settings within the .jnlp file, but perhaps this can be done with a manifest? I don't know how they work, so if that's the solution please supply an example.
Stuff in META-INF should not be readable by code in your jar file, since that code should be agnostic to the fact that it's packaged in a JAR. Instead, since it is meta information (meta-inf) about the Jar itself, only the application that loads the jar file should access it.

Tomcat - won't load my META-INF\services\javax.servlet.ServletContainerInitializer file?

I have a web project that has a \META-INF\services\javax.servlet.ServletContainerInitializer file with its content pointing to the fully qualified name of a class that implements the ServletContainerInitializer interface. I basically followed the example given here: http://nullhaus.com/2011/03/using-servlets-3-0-servletcontainerinitializer/
I put debug lines in my class that implements the ServletContainerInitializer interface and it never makes it there. Not even the default constructor...
My application folder structure is as follows:
\MyApp
\META-INF\services\javax.servlet.ServletContainerInitializer
\WEB-INF\classes\
... [list of classes and packages go here]
Any ideas what I need to check for??
Note 1: My Tomcat publishes from an exploded external folder that contains my application
Note 2: I started my Tomcat from Eclipse - if that makes a difference!
Well, I think that you'll need to wrap your initializer class (and it's services-related META-INF directory) into a separate *.jar and put it in the WEB-INF/lib.
This is a JAR service, so I guess it could have something to do with problems with discovering services in a *.war file. Moreover, it doesn't even help if you put your META-INF directory inside WEB-INF/classes and set unpackWAR=false in your Tomcat's server.xml.
HTH.
The first thing to check is that you are actually using Servlet 3.0 and not an earlier version. For Tomcat, this means that you must be using Tomcat 7.0.22
Second, make sure that the \META-INF\services\javax.servlet.ServletContainerInitializer file actually exists in the exploded war file.
Third, when in doubt, configure and start Tomcat directly (not from Eclipse) - I've seen developers have endless problems with configuration of Tomcat using the Eclipse plugin.
For tomcat to load the META-INF directory , it has to be in classes folder . If you are using maven project , just put the META-INF directory inside src/main/resources directory .. on mvn package the same will be copied to classes directory .. No need of separerate jar .. if jar is prefered you can use
HandlesTypes annotation ..
I would like to quote some good explanation from Mark Thomas <markt#apache.org> given on the user mailing list of Tomcat:
Service files are loaded by class loaders from the META-INF/services
directory.
*.jar!/META-INF/services
and
*.war/WEB-INF/classes/META-INF/services
are visible to class loaders
*.war!/META-INF/services
is not.
The servlet expert group recently discussed WAR vs JAR in the context of
Java 9 and mutli-version JARs. The conclusion was (I'm paraphrasing)
that WARs are not a specialised form of JAR and while they share a
common format a feature that is available to a JAR is NOT automatically
available to a WAR unless the Servlet spec (of Java EE spec) explicitly
states otherwise.
Containers are free to add container specific extensions if they wish
but they come with the usual (lack of) interoperability warnings.
http://mail-archives.apache.org/mod_mbox/tomcat-users/201808.mbox/

Categories