I am aware that this is a rather long and detailed post. I would have made it shorter and simpler if I could. I'd be grateful for any advice or ideas.
Background
I am writing XSLT to transfer data between two applications - call them Source and Target.
My XSLT is called by an integration engine supplied by the supplier of the Source System - call them Source Co.
The integration engine updates the Target by calling an adapter included in the engine that wraps an API written by the supplier of the Target system - call them Target Co. This all runs inside a J2EE server.
When the integration engine is deployed to the Java EE server it copies the JAR file implementing the Target System API so that it will be on the engine's classpath.
My situation
Source Co's Adapter that wraps Target CO's API only exposes a sub-set of the API. At times, my customers' business requirements can only be met by side-stepping the Source Co Adapter and calling the API directly from JAVA.
I have achieved this already by:
Writing Java classes that accept and return DOM documents and call the API
Deploying them as JARs into the Java EE engine so that they will be on the classpath visible to the integration engine and hence my XSLT
In my XSLT I point at the Java class by declaring a namespace and then call the appropriate public static method via that namespace
This all works well. However...
My Problem
Recent versions of Target Co's API have:
Removed several deprecated methods
Exposed access to additional business entities in the Target system
Source Co's adapter uses these removed methods and therefore it needs to have an old version of the Target Co API on its classpath.
A customer's latest business requirements can only be met by using the latest API to access these additional business entities.
My question
How can I have the latest version of the API on the classpath of my extension function without it being on the classpath for the integration engine's adapter?
I could use custom class loaders of course. I've done this to load a 3rd party database driver jar that would have also broken the integration engine if it had been on its classpath. In the database driver case, this involves just using the custom classloader once. In the current case, however, I can't see how I can avoid having many, many calls to the classloader littered all over my code and this feels very wrong.
Some technical details
Source System - SAP
Target System - Oracle's Primavera
Java EE Engine - Netweaver 7.2
XSLT Processor - Saxon
Related
I need a way to version my java service to be versioned like REST. I want to use the Semantic Versioning and manage my java api lifecycle same as REST.
Example:-
String runService(String serviceVersion, String inputToService...)
and based on the version it will call to appropriate functionality of the service.
I am thinking of loading separate versions of jar through classloader as descrived in Java, Classpath, Classloading => Multiple Versions of the same jar/project
Is there any best possible way to do this or shall I switch to REST.
I am writing a plugin API for a Java application, the idea being that eventually third parties will provide their own plugin extensions for the application and all the user needs to do is place the plugin jar into a plugins directory of the application. For the impatient, my question in short is how to handle possible version conflicts when the plugin relates to a different API than that on the system, see below for details of my situation and what I have thought about.
I have read a number of articles using service provider interfaces and have something working with that. The problem comes when considering how to deal with differing version combinations.
I am aware of the technique of when adding to an API adding extension interfaces, rather than changing the existing interface (eg. API 1.0 having MyInterface, API 1.1 adding MyInterface2 with the new methods, etc). With this technique if the user has the latest API then older plugins should work fine, but what happens if the user has an old API and newer plugins?
So as an example the user has API 1.0 only with MyInterface but installs binary plugin compiled against API 1.1 where the provider class implements MyInterface2. Whilst the application may only ever call plugins using MyInterface, what happens if the plugin internally calls MyInterface2? Will this cause an error or exception and when (IE. when the class is loaded or when the method from MyInterface2 is called). Also is this standard across JVMs or may it differ depending on the JVM used?
Finally, would it be better to use a plugin framework, would that be able to check version requirements? Searching the internet I find PF4J on github. A quick look in the source code seems to show it may support some sort of version checks.
I am writing a client (Eclipse RCP) that needs to be able to use multiple versions of a library (which encapsulates the backend interface). Each version of the library adds some new classes/methods that are used by the client. In case an older lib version is used, the client will access new classes/methods that are not present in the lib bytecode, resulting in NoClassDefFoundError.
So I am thinking of how to do this the best way. The most simple way to make it fail-safe is to wrap all calls to such code into try/catch blocks I guess. I was thinking of writing a custom annotation for marking new code in the library source, and then issue a compiler warning when such marked code is accessed from code that is not secured by try/catch (can this be done by a custom annotation? Haven't written one before). Or can someone think of a different approach that is more elegant?
You can use maven repository for providing different version of your library.
Maven central repository is available for releases:
http://maven.apache.org/guides/mini/guide-central-repository-upload.html
You can setup own instance of Artifactory: http://www.jfrog.com/confluence/display/RTF/Configuring+Maven+Deployment+to+Artifactory
I want to create a client in Java that connects to a web service which requires Digest authentication. Since I am not familiar with java and java stack, I've made a research and came across jax-ws, axis2, xcf, and metro. I have learned JAX-WS is an API and there is a reference implementation in the JDK but it lacks the digest authorization support.
My first attempt was to use axis2 since there is a built-in support for it in the Eclipse IDE. The following code seems to follow digest authentication workflow but somehow it still fails the authorization in the end.
Service1Stub stub = new Service1Stub();
HttpTransportProperties.Authenticator authenticator = new Authenticator();
List<String> authSchemes = new ArrayList<String>();
authSchemes.add(Authenticator.DIGEST);
authenticator.setAuthSchemes(authSchemes);
authenticator.setUsername("doman user");
authenticator.setPassword("domain password");
authenticator.setPreemptiveAuthentication(true);
Options options = stub._getServiceClient().getOptions();
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, authenticator);
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED, org.apache.axis2.Constants.VALUE_FALSE);
GetData getData = new GetData();
getData.setValue(25);
GetDataResponse data = stub.getData(getData);
System.out.println(data.getGetDataResult());
My second attempt was to use metro framework but I get some errors related to JAXB versions.
java.lang.LinkageError: JAXB 2.1 API is being loaded from the bootstrap classloader, but this RI needs 2.2 API.
I have to use JDK 1.6.0_03 so I guess this is happening because of a JDK version mismatch, but I also don't want to use the suggested "endorsed directory mechanism" because it might cause lots of troubles during deployment.
I am totally lost and I am looking for the simplest, quickest and up-to-date way of consuming a web service that requires Digest authentication in Java? Preferably with as little as dependencies possible.
Java classloading is a mess, sorry. The root cause is that there are no strong names like there are in the .NET world, and therefore the runtime linker takes whatever match comes first on the classpath, regardless of whether that's the library version that the code was compiled against. The OSGi system solves this problem, but it never gained mainstream adoption.
The error message you cited:
java.lang.LinkageError: JAXB 2.1 API is being loaded from the bootstrap classloader, but this RI needs 2.2 API.
is uncharacteristically useful and specific, most of the time what happens instead is that you're left staring at a NoSuchMethodError or something of the sort. Over time, you learn to recognise these as library version mismatches. In this case, the library author(s) have written code to recognize a common error case and print a better error message (bless 'em).
Rant over, here's some info that I hope will set you on the right track:
Java classloaders are hierarchical and resolution is bottom-up
but there's a blessed class loader at the root of the hierarchy that's responsible for loading the core runtime library
vendor shenanigans have led to a lot of stuff getting included in the core runtime library that really shouldn't have been in there, as it's a shortcut to becoming dominant in an otherwise Darwinistic selection process. JAXB is one of these things, as you've just found out. JAXB2 is actually pretty decent, but it evolves independent of the core runtime and, well, here we are.
the JDK and JRE installation has a folder called lib\endorsed where you can add JAR files that need to be loaded by the root loader, bypassing even what's in rt.jar.
In summary, if you manually add the 2.2 version of the JAXB library to %JAVA_HOME%\lib\endorsed, then it should override the included 2.1 version and your web service client will deploy. This will have to happen on every system that will run the web service client, until the JDK is updated to a 7.x version that does included JAXB 2.2. If the same JVM is running other JAXB based applications, these may or may not break as a result.
Yes, this is painful. A tangent that you could investigate is to deliberately use an older version of Metro that's built for JAXB 2.1. So long as you're bound to deploying on 1.6.0_03, this may well be the better option, despite losing some of the recent improvements in Metro.
Updated: here's a blog post on this topic. It contains some links to further information.
Metro framework was way too complicated to configure and documents that I have found were incomplete. So I've done it with using Apache Axis2.
Steps to follow:
Download and extract Apache Axis2 binaries.
Reference to all jar files
Go to /bin folder and use wsdl2java to generate client code.
wsdl2java -S src -uri "wsdl_file_location"
Copy everything under the src folder to your java application and connect to the service as follows:
//Fictious is the name of the web service
FictiousStub stub = new FictiousStub("servicelocation/fictiousService.php");
HttpTransportProperties.Authenticator authenticator = new Authenticator();
List<String> authSchemes = new ArrayList<String>();
authSchemes.add(Authenticator.DIGEST);
authenticator.setAuthSchemes(authSchemes);
authenticator.setUsername("admin");
authenticator.setPassword("12345");
authenticator.setPreemptiveAuthentication(true);
Options options = stub._getServiceClient().getOptions();
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, authenticator);
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED, org.apache.axis2.Constants.VALUE_FALSE);
I just installed the Google Eclipse plugin and created my first test Web Application Project (using both GWT and GAE SDKs). The plugin autogenerated a project that had a war/ directory in it that had some peculiar subdirectories and files in it. An online search for many of these only returned other similar autogenerations of them but without any real explanation of what they are, or what they do:
war/WEB-INF/deploy/<myapp>/rpcPolicyManifest/**
war/WEB-INF/deploy/<myapp>/symbolMaps/**
war/<myapp>/symbolmanifest.json
gwt-unitCache/**
I'm also a litte confused about what the proper structure should be for a GWT WAR that is going to be deployed to GAE. What content should be packaged under war/WEB-INF/? What content should be packaged under the war/ root? Any other special considerations for GWT/GAE WARs? Thanks in advance!
Almost everything in the war/ folder is deployed to GAE. With the exception of temp-files that are used by the plugin, such as war/WEB-INF/appengine-generated/
The war/WEB-INF/ folder contains things needed to set up the GAE. This includes GAE settings for servlets, queues, logging, RPC etc. It also includes libraries that are used server-side and some GWT-mappings.
Note that the GWT libraries only are needed at compile-time and not on the server. You can put all GWT libraries in a lib/ folder outside of war/.
war/WEB-INF/deploy/<myapp>/rpcPolicyManifest/**
RPC is used to call server-methods directly from GWT-code. GWT/GAE is designed to allow RPC out-of-the-box. My guess is that the existence of a RPC policy manifest file is enough to configure GAE to allow the GWT code to use RPC, so they just put it there so you don't have to worry about it.
war/WEB-INF/deploy/<myapp>/symbolMaps/**
The plugin automatically adds the things needed here, so you don't have touch it. But the symbolMaps appear to be a dictionary used by GWT to supply different version of the app based on browser version. The first few lines in one of my symbolMap files read like this:
# { 1 }
# { 'user.agent' : 'gecko1_8' }
# jsName, jsniIdent, className, memberName, sourceUri, sourceLine
Duration,,com.google.gwt.core.client.Duration,,jar:file:/opt/eclipse/plugins/com.google.gwt.eclipse.sdkbundle_2.4.0.v201208080121-rel-r42/gwt-2.4.0/gwt-user.jar!/com/google/gwt/core/client/Duration.java,21
Which specifies how the JavaScript symbol 'Duration' should be interpreted, given that the user agent is gecko 1.8. Each browser-compilation (FF, Opera, Safari, IE etc.) has it's own mapping, allowing for browser-specific optimizations by the GWT compiler.
war/<myapp>/symbolmanifest.json
I don't have this file in my project, but it's probably related to the GWT symbol maps mentioned above. My guess is that it defines the JavaScript symbols that the GWT app uses. If you post a snippet from it we'll be able to see if this is the case.
gwt-unitCache/**
This is a cache-folder that is only used during development. See the release notes for GWT 2.4.0:
Persistent Unit Cache: GWT Compiler and Development mode now cache
compilation artifacts between runs. This results in faster startup
time for iterative development.