Workaround for JAX-WS NullPointerException when calling web service from embedded Java 8 JVM

[Note: I originally posted this solution to Stackoverflow.com]

Problem:

When connecting to a SOAP based web service from a Java 8 embedded JVM using JAX-WS dynamic generation of the client stubs, you get this NullPointerException:

If your problem is the same as mine, you will also have the symptom that this problem did not occur under Java 6, but now all of a sudden is happening under Java 8.

Solution:

For me, the main conditions under which this problem occurs is:

  1. Java 8 running as an embedded JVM via jvm.dll from within a Windows program. I tried to reproduce the problem running in a standalone Java 8 JVM and I couldn’t get it to happen. Running standalone was very helpful in diagnosing the problem, however.
  2. Using the proxy method of initializing the connection to a JAX-WS web service, which dynamically creates the stub on the client side using the WSDL hosted on the server side.

Workaround:

When you invoke the call to Service.getPort(Class<T>) it needs to be done in its own thread, separate from the thread you had the call running in previously. What this allows for you is an opportunity to set the ClassLoader on that thread to a ClassLoader that is not the bootstrap classloader, which is the crux of the problem in ClientContainer.java (more explanation on that below). Here is some sample code that is working for me. You will have to modify it to suit your needs.

Additional Background and Details:

The difficulty in diagnosing this for me was that the problem only occurred inside of a Windows product which launches an embedded JVM. Without remote debugging on that JVM, it would have taken much longer to get to the bottom of the problem. Once I saw that 1) when I ran the same code which invokes the call to Service.getPort(Class<T>) inside of a standalone JVM (outside of the Windows product) and, 2) that the ClientContainer class was able to get the current thread’s ClassLoader and, 3) that the ClassLoader returned wasn’t the bootstrap ClassLoader (i.e., not null), it made me realize that I had to find a way to ensure that the thread that the ClientContainer was running in would not get the bootstrap ClassLoader. The goal then became to see if I could find a way to alter the ClassLoader resolved by the ClientContainercode.

ClientContainer source: click to view

Notice in the ClientContainer source that there are two attempts to resolve a classloader. The problem is that if both of those attempts return the bootstrap classloader, a NullPointerException will result on line 45 since cl will be null:

This workaround ensures that the classloader resolved by the ClientContainer code will be the classloader that you set on your thread.

I’ve filed a ticket for the JAX-WS team to investigate the problem here: https://java.net/jira/browse/JAX_WS-1178

Posted in Java | Tagged , , , , , , | 2 Comments

Curl command line encoding of query parameters for an HTTP PUT

[Note: I originally posted this problem/solution to Stackoverflow.com]

Problem:

I have multiple query parameters that I want to send in an HTTP PUT operation using curl. How do I encode the query parameters? Example:

If ‘value 1’ contains spaces or other characters that are interpreted by the shell, the command will not parse correctly.

Solution:

The solution is to use the -G switch in combination with the --data-urlencode switch. Using the original example, the command would look like the following:

The -G switch causes the parameters encoded with the --data-urlencode switches to be appended to the end of the http URL with a ? separator.

In the example, the value of param1, would be encoded as value%201, where %20 is the encoded value for a space character.

Posted in Unix | Tagged , , , , | Leave a comment

SQL Server JDBC Error on Java 8: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption

[Note: I originally posted this problem/solution to Stackoverflow.com]

Problem:

I am getting the following error when connecting to a SQL Server database using version the Microsoft JDBC Driver:

 

We recently upgraded our applications from Java 6 & Java 7 to Java 8. All systems running Java are running SUSE Linux Enterprise Server 11 (x86_64), VERSION = 11, PATCHLEVEL = 3.

Here are the facts I have collected with a Java program that I wrote which simply sequentially opens and closes 1,000 database connections.

  • Connections are dropped with this error about 5%-10% of the time. The error DOES NOT occur on every connection.
  • The problem ONLY occurs with Java 8. I ran the same program on Java 7 and the problem is not reproducible. This is consistent with our experience in production prior to upgrading. We’ve had zero problems running under Java 7 in production.
  • The problem DOES NOT occur on all of our Linux servers running Java 8, it only occurs on some of them. This is perplexing to me, but when I run the same test program on the same version of the Linux JVM (1.8.0_60, 64 bit) on different Linux instances, the problem does not occur on one of the Linux instances, but the problem does occur on others. The Linux instances are running the same version of SUSE and they are at the same patch level.
  • The problem occurs when connecting to BOTH SQL Server 2008 and SQL Server 2014 servers/databases.
  • The problem occurs regardless if I am using the 4.0 version of the SQL Server JDBC driver or the newer 4.1 version of the driver.

The thing that makes my observations unique on this compared to others on the web is that although the problem happens ONLY on Java 8, I cannot get the problem to occur on one of the seemingly identical Linux servers that is running the same Java 8 JVM. Other folks have seen this problem on earlier versions of Java as well, but that has not been our experience.

Any input, suggestions, or observations you may have are appreciated.

 

Solution

I turned on SSL logging in the Java 8 JVM on a Linux instance which reproduces the problem. SSL logging is turned on using -Djavax.net.debug=ssl:handshake:verbose. This revealed some useful information.

The workaround that we are using in production and has proven to work for us is to set this parameter on the JVM:

-Djdk.tls.client.protocols=TLSv1

If you want more details, please read on.

On a server where the problem can be reproduced (again, only 5-10% of the time), I observed the following:

Notice that TLSv1.2 is selected by the database server and used in this exchange. I’ve observed that, when connections fail from the problematic linux service, TLSv1.2 is ALWAYS the level which was selected. However, connections do not ALWAYS fail when TLSv1.2 is used. They only fail 5-10% of the time.

Now here is an exchange from a server that does NOT have the problem. Everything else is equal. I.e., connecting to the same database, same version of the JVM (Java 1.8.0_60), same JDBC driver, etc. Notice that, here, TLSv1 is selected by the database server instead of TLSv1.2 as in the faulty server’s case.

So, when TLSv1 is negotiated between the Linux JVM and the SQL Server, connections are ALWAYS successful. When TLSv1.2 is negotiated, we get sporadic connection failures.

(Note: Java 7 (1.7.0_51) always negotiates TLSv1, which is why the problem never occurred for us with a Java 7 JVM.)

The open questions we still have are:

  1. WHY is that the same Java 8 JVM run from 2 different Linux servers will always negotiate TLSv1, but when connecting from another Linux server it always negotiates TLSv1.2.
  2. And also why are TLSv1.2 negotiated connections successful most, but not all, of the time on that server?

Resources:

http://www.infoworld.com/article/2849292/operating-systems/more-patch-problems-reported-with-the-ms14-066-kb-2992611-winshock-mess.html

http://www.infoworld.com/article/2849292/operating-systems/more-patch-problems-reported-with-the-ms14-066-kb-2992611-winshock-mess.html

http://blogs.msdn.com/b/jdbcteam/archive/2008/09/09/the-driver-could-not-establish-a-secure-connection-to-sql-server-by-using-secure-sockets-layer-ssl-encryption.aspx

Java 8 , JCE Unlimited Strength Policy and SSL Handshake over TLS

http://blogs.msdn.com/b/saponsqlserver/archive/2013/05/10/analyzing-jdbc-connection-issues.aspx

https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#descPhase2

https://blogs.oracle.com/java-platform-group/entry/java_8_will_use_tls

 

Posted in Java | Tagged , , , , | Leave a comment

Spring 4.1 MVC + Hibernate 4.3 + Webflow 2.4 + OpenSessionInViewFilter = java.lang.IllegalStateException, Already value for key bound to thread

[Note: I originally posted this problem/solution to Stackoverflow.com]

Problem:

I am upgrading an application from these component versions to their latest counterparts:

I am currently very stuck on a problem related the OpenSessionInViewFilter and Spring Webflows. None of the code pertaining to my webflow is even executed, the problem occurs upon initialization of the webflow and Hibernate SessionHolder. I have not changed the webflow configuration during this Spring/Hibernate upgrade and everything has been working fine in production for almost 6 years. I am getting the following exception for which there is little help available on the web. The stack trace is a mile long, so I am including what I think are the important parts.

Pertinent parts of web.xml:

Pertinent parts of Application Context configuration:

Webflow configuration file:

It seems that the OpenSessionInViewFilter is creating the Hibernate Session first, then the HibernateFlowExecutionListener is attempting to create one rather than using the one created by the OpenSessionInViewFilter thus causing the "Already value [org.springframework.orm.hibernate4.SessionHolder@xxxxxxxx] for key [org.hibernate.internal.SessionFactoryImpl@xxxxxxxx] bound to thread [xxxxxxxxxxxxxxx]"error.

Any ideas on what I can tweak or further delve into for troubleshooting? Any solutions or workarounds? Anyone else seen this? Thank you for the help!

Solution

My solution to this was to split out my Web Flows from being handled by the OpenSessionInViewFilter. Before I made the change, all URLs in the app that ended in *.htm were routed through the OpenSessionInViewFilter. This was my web.xml before the changes:

Now my web.xml has this configuration:

Notice that I added a new *.flow url-pattern to my filter-mapping for the openSessionInViewFilter and I now have a custom class that overrides the Spring OpenSessionInViewFilter (more on that below). I then had to change the URL suffix of the places in my views (and controllers in a few cases) where I invoked webflows from using ‘.htm’ to using ‘.flow’.
So, for example, if I had previously used webflow url of ‘/customer/customer-add.htm’, I changed it to ‘/customer/customer-add.flow’.

The next piece is that I added a class derived from Spring’s OpenSessionInViewFilter whose purpose was to pass all *.htm URLs to the OpenSessionInViewFilter while simply forwarding all *.flow URLs to the next filter in the chain (thereby allowing the HibernateFlowExecutionListener to eventually handle the URL and manage the session properly):

Finally, please note that you should leave the Spring configuration you already have for the HibernateFlowExecutionListener alone — no changes required there:

 

Posted in Java | Tagged , , , , | Leave a comment

How to require a particular Java version for compilation using Maven

Lately we’ve had a few instances at my current client where we’ve had problems with deployment of Java web apps which have been built using the wrong JDK version.  We are using Atlassian Bamboo for continuous integration on our daily builds, but we have not yet set up automated releases using Bamboo.  Thus, we still have developers creating releases on their individual workstations instead of on a dedicated build machine or cluster.  The problem with this is that if an individual developer is not careful with his/her environment set up, they can inadvertently build a release using the wrong JDK version.

I recently discovered that the Maven Enforcer plugin can help prevent this from happening.  Configuring it in your Maven build is really quite easy.  I’ve included an example below that shows how to require that your Java project be built using Java 1.7.

 

Posted in Java | Tagged , , , , , , , | Leave a comment