Spring initializer class not found by Tomcat when using Java 16 - java

I have a very simple Gradle (7.0-rc-1) script to initialise a single Spring 5 "hello world" endpoint using an embedded Tomcat instance. The original code is taken from a random example I found on the internet.
My example Gradle project can be found here.
I'm not sure how it works but somehow the web server knows to call the WebApplicationInitializer.onStartup(ServletContext) method on startup so that Spring is intialised.
This works correctly on Java 8; but fails when I change the following toolchain specification in the Gradle build definition to Java 16.
java {
toolchain {
// languageVersion = JavaLanguageVersion.of(16)
languageVersion = JavaLanguageVersion.of(8)
}
}
When using Java 8, Spring is intialised correctly and the endpoint works.
When using Java 16, The onStartup() method is not called, so Spring is not initialised and the endpoint doesn't work (though Tomcat is still started and responds with an error).
The logging shows a message like, there is no stacktrace though:
INFO: No Spring WebApplicationInitializer types detected on classpath
What do I need to do to make this work on Java 16?
Note that I don't want to use spring-boot, please don't suggest it.

I've found a workaround that gets Spring configured and responding to the /hello endpoint. But I don't know why it works or if it's the right thing to do.
If someone can answer the question with an explanation of what's going on with Java 16 - I will gladly mark that as the accepted answer.
Workaround
My work around is to programmatically add the ServletContainerInitializer class.
So where before I was just calling the addWebapp() method:
tomcat.addWebapp("", appBase);
I now add my Spring intializer explicitly:
Context appContext = tomcat.addWebapp("", appBase);
appContext.addServletContainerInitializer(new SpringAppConfig(), null);
Updated code on Github.

Related

Java service using Jersey won't deploy to Jboss

I'm trying to build a Java service that other services could call.
This service is not a WS, but is calling a RestfulWS.
I'm really just building a wrapper around this call. This would find the correct data it needs, set up the JSON for the call. Get a response and send it back up.
Was told to use Jersey for this. Trying to set up all the pom.xml to use Jersey.
Building code works fine, it is when the deploy to the server happens that things fail.
I get the error -- "JBAS011232: Only one JAX-RS Application Class allowed. "
I don't have a web.xml, which I guess is used to skip some ResetEasy files.
I do have exclusions in pom.xml and jboss-deployment-structure.xml.
I still get the error when deploy happens. Not really sure what else to check.
It looks like you have a problem with JAX-RS dependencies. JBoss already has its own implementation of JAX-RS and probably that’s causing the issue. Some solutions are already suggested here Jboss error: Only one JAX-RS Application Class allowed

Jboss wildfly 10 strange issue loading libraries

I'm developing a custom application for IBM BPM that uses these libraries: Jace.jar, pe.jar, log4j.jar, stax-api.jar, xlxpScanner.jar and xlxpScannerUtils.jar that are used to call a web service.
When I create a java project and add those libraries, it works fine. It also works ok when I create a dynamic web project using tomcat 8 as server; but when using jboss I don't get the expected result when calling the web service. So, does anybody know how to disable the modules that use these libraries? Or where to find information about it?
I want my application to be server independent.
This is my code:
try {
VWSession vwSession = new VWSession("userName", "userPass", "connPt");
vwSession.isLoggedOn(); /* It's loaded with 'false' value in jboss.
In tomcat it's loaded with 'true' value */
} catch (Exception e) {
Logger.getLogger(getClass().getName()).log(Level.FATAL, "Details: ", e);
}
To create an application that is server agnostic, you need to strictly adhere to Java EE specification. Meaning, use only those jars that are bundled as part of the Java EE version you are using. Then too, there are certain deployment descriptors specific to a given application server that would need to be used in some cases. For example - jboss-deployment-structure.xml, ibm-application-bnd.xml, etc.
In your case, xlxpScanner.jar is not a part of the Java EE spec, so making the application server independent is not possible with the current settings. You could look for a replacement of the part of this jar you are using with something Java EE has. In short, get rid of this jar alongwith xlxpScannerUtils.jar.
Alternatively, if you want jboss to run the application properly, add all the jars in a module and give it to the EAR/WAR using jboss-deployment-structure.xml. Details can be found here.

Exception when using #SchemaValidation annotation on JAX-WS endpoint in Weblogic

I am trying to get schema validation working for a JAX-WS Web Service deployed on Weblogic 10.3.3.
According to the documentation, this should be as simple as adding the annotation
"#SchemaValidation" to the endpoint class. However when I try this the following exception is thrown when the application is deployed:
Caused by: javax.xml.ws.WebServiceException:
Annotation#com.sun.xml.internal.ws.developer.SchemaValidation
(handler=class com.sun.xml.internal.ws.server.DraconianValidationErrorHandler)
is not recognizable,
atleast one constructor of class com.sun.xml.internal.ws.developer.SchemaValidationFeature
should be marked with #FeatureConstructor
at com.sun.xml.ws.binding.WebServiceFeatureList.getWebServiceFeatureBean(WebServiceFeatureList.java:169)
at com.sun.xml.ws.binding.WebServiceFeatureList.parseAnnotations(WebServiceFeatureList.java:141)
The error message is complaining that "com.sun.xml.internal.ws.developer.SchemaValidationFeature" does not have a constructor annotated with #FeatureConstructor. When I look at that class, it sure seems to have one:
#com.sun.xml.internal.ws.api.FeatureConstructor(value={"handler"})
public SchemaValidationFeature(java.lang.Class arg0);
I have googled around but cannot find any reference to this more than this fellow unfortunate soul who did not get any answers. It would be great if someone could point me in the right direction because at this moment I am stuck.
SchemaValidation annotation is working, but make sure you're importing correct class.
com.sun.xml.ws.developer.SchemaValidation
instead of
com.sun.xml.internal.ws.developer.SchemaValidation
The second class is bundled with JDK by default. The first one (used by weblogic) comes from glassfish.jaxws.rt_XXX.jar, so you may need to add this jar to your classpath explicitly.
I have faced the same problem recently.
To overcome this, I added the tag
<validation-request>true</validation-request>
to the file weblogic-webservices.xml
This enabled SOAP request validation on the app-server.
XML Structure of weblogic-webservices.xml
Note : I have not been able to use the #SchemaValidation tag successfully, but the above way - works as expected.

Web Service Client in JBOSS 5.1 with JDK6

This is a continuation of the question here:
JBoss - does app have to be compiled under same jdk as JBOSS is running under?
It's different enough though that it required a new question.
I am trying to use jdk6 to run JBOSS 5.1, and I downloaded the JDK6 version of JBOSS 5.1. This works fine and my EAR application deploys fine. However, when I want to run a web service client with code like this:
public static void main(String[] args) throws Exception {
System.out.println("creating the web service client...");
TestClient client = new TestClient("http://localhost:8080/tc_test_project-tc_test_project/TestBean?wsdl");
Test service = client.getTestPort();
System.out.println("calling service.retrieveAll() using the service client");
List<TestEntity> list = service.retrieveAll();
System.out.println("the number of elements in list retrieved using the client is " + list.size());
}
I get the following exception:
javax.xml.ws.WebServiceException: java.lang.UnsupportedOperationException: setProperty must be overridden by all subclasses of SOAPMessage
at org.jboss.ws.core.jaxws.client.ClientImpl.handleRemoteException(ClientImpl.java:396)
at org.jboss.ws.core.jaxws.client.ClientImpl.invoke(ClientImpl.java:302)
at org.jboss.ws.core.jaxws.client.ClientProxy.invoke(ClientProxy.java:170)
at org.jboss.ws.core.jaxws.client.ClientProxy.invoke(ClientProxy.java:150)
Now, here's the really interesting part. If I change the JDK that my the code above is running under from JDK6 to JDK5, the exception above goes away! It's really strange.
The only way I found for the code above to run under JDK6 was to take the JBOSS_HOME/lib/endorsed folder and copy it to JDK6_HOME/lib. This seems like it shouldn't be necessary, but it is.
Is there any other way to make this work other than using the workaround I just described?
Looks roughly as if you ran into the presence of JAX-WS as an official feature of JDK 1.6. Don't copy things to 'lib', copy them to an 'endorsed' directory (one listed in java.endorsed.dirs). This might be helpful.
If you have an up-to-date 1.6, you can get around this the same way that Apache CXF does. See the documentation for information on how to use CXF in a 1.6 environment.
There are various suggestions and explanations in the respective bug report and elsewhere (e.g. here and here). I don't know how well they work.
Information about this issue you can find in JBoss official Installation And Getting Started Guide:
http://docs.jboss.org/jbossas/docs/Installation_And_Getting_Started_Guide/5/html/Installation_Alternatives.html

Datasource creation failed using PCF User Provided Service

I have a SpringBoot application and deploying it in PCF where app is trying to connect Oracle 12c Database using PCF User Provided Services but it failing with this error Failed to determine a suitable driver class
build.gradle code:
and here are the configuration that I used in CUP service:
Service binding is happening properly. I can see the same details under VCAP_SERVICES in Environment Variables.
Error:
Short Answer: I think you want the uri to be oracle://... Strip off the jdbc: part. The Spring Autoreconfiguration code that gets injected by the Java buildpack will look at the prefix on the URI, so it needs oracle:// to know it's an Oracle link.
Long Answer: You probably don't want to depend on the injected Spring Autoreconfiguration. When it just works, it's great, but it can be difficult to understand what it's doing when it doesn't work.
It is better to use Spring Cloud Connector or even better, as all signs point to this replacing Spring Cloud Connector, use java-cfenv. For details on java-cfenv, see this blog post.
Spring Cloud Connector has the same issue I mentioned above as the Spring Autoreconfiguration, except that it will pretty clearly tell you when it doesn't recognize a bound service. Anyway, if you decide to use SCC, make sure you prefix the URI with oracle://.
If you use java-cfenv, it's more flexible so it's really up to you what properties and values you inject through the service.
Hope that helps!

Categories