Websphere 8.5 with Spring-5 - spring

Is Websphere 8.5.5 compatible with Spring 5? The Validation API referenced in spring5 (validation-api 5) is resulting in MethodNotFound exception.. Any pointers/patch available to get this solved - short of upgrading to Websphere 9?
Caused by: java.lang.NoSuchMethodError:
javax/validation/Configuration.getDefaultParameterNameProvider()Ljavax/validation/ParameterNameProvider;
(loaded from
file:/opt/IBM/WebSphere/AppServer/plugins/javax.j2ee.validation.jar by
org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader#25d460de)
called from class
org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
(loaded from file:../spring-context-5.0.2.RELEASE.jar by
com.ibm.ws.classloader.CompoundClassLoader#1c7dbdd9

The method javax/validation/Configuration.getDefaultParameterNameProvider was added in Bean Validation 1.1, so that indicates the Spring Validator you are using is attempting to use the Bean Validation 1.1 API. According to https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.html:
As of Spring 5.0, this class requires Bean Validation 1.1+
WebSphere 8.5.5 provides Bean Validation 1.0 and did not add support for Bean Validation 1.1 until version 9.0. So, you'll either need to use Spring 4.x or WebSphere 9.x.

The above answer is not correct. You can run Spring 5 in WebSphere 8.5. This may not be the perfect solution for your situation, but this will get you on the correct path.
1.) Provide your Bean Validation 1.1 JAR
Here is a sample of the Maven dependency.
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
2.) Add the following a deployment.xml file to the following location in your EAR file.
/myAppEAR/META-INF/ibmconfig/cells/defaultCell/applications/defaultApp/deployments/defaultApp/deployment.xml
3.) In the contents of your deployment.xml file, you must set the classloaderMode to PARENT_LAST. You must also modify this code to use the correct WAR file name.
Here is a sample...
<appdeployment:Deployment xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:appdeployment="http://www.ibm.com/websphere/appserver/schemas/5.0/appdeployment.xmi" xmi:id="Deployment_1422578178899">
<deployedObject xmi:type="appdeployment:ApplicationDeployment" xmi:id="ApplicationDeployment_1422578178899" startingWeight="10" warClassLoaderPolicy="SINGLE">
<modules xmi:type="appdeployment:WebModuleDeployment" xmi:id="WebModuleDeployment_1422578178899" startingWeight="10000" **uri="myApp.war"** **classloaderMode="PARENT_LAST"**/>
<classloader xmi:id="Classloader_1422578178899" **mode="PARENT_LAST"**/>
</classloader>
</deployedObject>
</appdeployment:Deployment>

#rob-breidecker is correct, this is possible even though WebSphere 8.5.5 provides Bean Validation 1.0. To do this, you need to change the classloader of your application.
To do that via the UI, go to Applications -> WebSphere enterprise applications -> Your Application -> Class loading and update detection and change the Class loader order to be Classes loaded with local class loader first (parent last). This "causes the class loader to attempt to load classes from its local class path before delegating the class loading to its parent.".
If you are deploying an EAR and want this change to propagate to inner applications, you can either change WAR class loader policy to Single class loader for application or change the class loader of the individual war (in the EAR click Manage Modules -> Your Module then change Class loader order).
As long as you provide a version of validation-api (I used 2.0.1.Final), you should get passed the above issue.
The following wasadmin.sh script will apply the above settings (replace app_name with the name of your application): (credit)
dep = AdminConfig.getid('/Deployment:app_name/');
depObject = AdminConfig.showAttribute(dep, 'deployedObject');
AdminConfig.modify(depObject, [['warClassLoaderPolicy', 'SINGLE']]);
classldr = AdminConfig.showAttribute(depObject, 'classloader');
AdminConfig.modify(classldr, [['mode', 'PARENT_LAST']]);

I though at some point it was impossible to do this, but finally, I found a solution, you can use spring 5.X and Boot 2.X with WebShpre 8.5 using the below Steps, just make sure that you project is compatible with:
1- Bean Validation
2- Servelt 3.1
Steps:
1- Create a custom folder on you server for example /opt/custom/lib/spring5 and upload below jars to this folder
a. jakarta.el-3.0.4.jar
b. jakarta.validation-api-2.0.2.jar
2- Create a new shared library in WebSphere as below
a. Go to environment -> shared library
b. Chose the scope to node and server
c. Click on New and fill the value with below
i. Name: spring5
ii. Class path: /opt/custom/lib/spring5
iii. Enable checkbox “use an isolated class loader for this shared library”
3- Restart the server
4- Go to Enterprise Application Click on the application (WAR/EAR)
5- Go To shared library reference add assign it to you application (WAR/EAR)
6- Go to Enterprise Application Click on the application (WAR/EAR)
7- Choose Classes loaded with local class loader first (parent last)
8- Restart the server

In case someone still needs a solution, the only way it worked for me was to change the file https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.html
from 5.x to use the logic from 4.x

Related

Upgraded my webapplication to use OJDBC8.jar. but Websphere8.5 refers to old version ojdbc6 and returns nosuchmethoderror

Error 500: java.lang.NoSuchMethodError: oracle/jdbc/OracleConnection.createOracleArray(Ljava/lang/String;Ljava/lang/Object;)Ljava/sql/Array; (loaded from file:/sysap/oracle/instantclient_11_2/ojdbc6.jar by com.ibm.ws.bootstrap.ExtClassLoader#96620801) called from class com.model.dao.TypeKeysDAO (loaded from file:/opt/WebSphere/8_5/AppServerBase1/profiles/AppServerBase1/installedApps/System_Cell/MyEnterprise.ear/MyEnterpriseWeb.war/WEB-INF/classes/ by com.ibm.ws.classloader.CompoundClassLoader#3edbaa21
The old copy of the JDBC jar appears to be associated with a JDBC provider defined in your configuration. The error message indicates that the class was loaded by WebSphere's ExtClassLoader, which is the loader that contains JDBC driver class paths. You'll need to remove the old JDBC provider, update its class path, or make it an "isolated" resource provider (which gives it a separate class loader that must be explicitly associated with an application) in order to get it out of the view of your application.
If there's some technical reason that you need ojdbc6.jar in the resource provider class path but need to reference ojdbc8.jar just within your application (not through a server-configured datasource), then you'll need to do some class loader configuration wizardry to make it work. The most reliable solution would be to create a shared library containing the new jar, set it to use an isolated class loader, and associate it with your EAR or WAR.
ojdbc6.jar is definitely there in the class path of the application. To locate from where it's loaded, you can login to the WebSphere Application server console (https://localhost:<admin-port>/ibm/console) and check the class loading details of your application.
This will show the list of classes/jars that are loaded for your application. Locate ojdbc6.jar from the list and see it's path.
You either would have added the ojdbc6.jar as a shared library or bundled in along with your Application (WEB-INF/lib directory) OR mentioned it in the class loader of the server itself.
file:/sysap/oracle/instantclient_11_2/ojdbc6.jar this is the sharedlibrary referenced by the EAR. I have added the ojdbc8.jar in this location and now the issue is fixed.

Deploying BEAN in OSGi plugin

I am currently deploying my custom controls as OSGi plugins and I wanted to do the same thing with my beans. I have tried putting them into the OSGi plugin and it works fine but the only problem I have is the faces-config.
It seems it has to be called faces-config in the OSGi plugin to work but that means i can't use beans in the NSF anymore because it seems to ignore the local faces-config.
Is there a way to change the name of the faces-config in the OSGi plugin?
Something like FEATURE-faces-config.xml?
In the class in your plugin that extends AbstractXspLibrary, you can override "getFacesConfigFiles", which should return an array of strings representing paths within the plugin to additional files of any name to load as faces-config additions. For example:
#Override
public String[] getFacesConfigFiles() {
return new String[] {
"com/example/config/beans.xml"
};
}
Then you can put the config file in that path within your Java source folder (or another folder that is included in build.properties) and it will be loaded in addition to your app's normal faces-config, beans and all.
The NSFs are running as separate, distinct Java applications. The OSGi plugin is running in the OSGi layer, above all those distinct Java applications, as a single code base. Consequently, the faces-config is only at that level.
It's possible to load them dynamically, by using an ImplicitObjectFactory, loaded from an XspContributor. That's what is done in OpenNTF Domino API for e.g. userScope (which is a bean stored in applicationScope of an NSF). See org.openntf.domino.xsp.helpers.OpenntfDominoImplicitObjectFactory, which is referenced in OpenntfDominoXspContributor, loaded via the extension point of type "com.ibm.xsp.library.Contributor".
A few caveats:
You have no control over what happens if you try to register your bean with a name the developer also uses for a different variable in that scope.
Unless you add code to check if the library is enabled, as we do, you'll be adding the bean to every database on the server.
You still need to add the library to the NSF. Unless you also provide a component that those databases will all use, there's no way you can programmatically add it, as far as I know.
It might be easier to skip the bean approach and just add an instance of the Java class in beforePageLoad, page controller class, or however you're managing the backing to the relevant XPage (if viewScope) or application (if sessionScope / applicationScope).

Linkage error in websphere 8.5 for SAXParser

I am facing an issue related to linkage when i deployed my application websphere 8.5
Error in the XML parsing of the included Input Stream: java.lang.LinkageError: loading constraint violation when resolving method "javax/xml/parsers/SAXParser.parse(Lorg/xml/sax/InputSource;Lorg/xml/sax/helpers/DefaultHandler;)V" : loader "com/ibm/ws/classloader/CompoundClassLoader#aa54261e" of class "com/XMLParser/CreateParser" and loader "com/ibm/oti/vm/BootstrapClassLoader#1c4565b7" of class "javax/xml/parsers/SAXParser" have different types for the method signature.
I have the following jars in my class path.
I have set the loader to PARENT_LAST.
I tried to debug the class alone using a main method and found that it is taking the impl of saxparser of jdk 1.5 rt.jar and it is working as expected. After deploying the ear it is throwing the exception while the code hits the SAXParser.parse(InputSoruce,DefaultHandler) method.
jaxb-impl 2.2.6,
jaxb-libs-1.0.5,
jaxb-xjc-2.0EA3,
dom4j-1.1,
sax 2.0.1
Does any one have any idea about this problem?
Your class loader has visibility to two copies of org.xml.sax. The first because you've included the SAX APIs in your PARENT_LAST class loader, and the second indirectly via javax.xml.parsers in the JRE. You either need to remove the SAX API JAR from your application or you need to add the javax.xml (and perhaps more) APIs + impl to your application.

Spring configuration - Multi module Maven project

I have a big web application. As part of optimizing the code, I've split them in to three modules.
Module 1 : Web
Module 2 : driver module
Module 3 : Reporting module
Here Module 1 & Module 3 are spring projects, where as the module 2 is currently pure Java module.
I want to access the Module 3(which is in spring) through Module 2.
App context xmls are present for module 1 and module 3. (say m1.xml and m3.xml)
I've included m3.xml in m1.xml as
<import resource="classpath*:m3.xml" />
In Module 2, I'm trying to introduce autowiring reference to classes in Module 3. But the first usage of the autowired field throws a Null Pointer exception.
In component scan, I've added the base package, so that it will be able to identify the class.
Can any one guide me how to rewrite Module 2 to fix this issue (ApplicationContext xml ? etc)
I'm using spring 3.1
I figured out the issue !
Actually from Module-1(webapp), I'm calling the driver module and from there calling the reporting modules.
The issue was that from driver to report, I'm calling using new references (new Report() ), so these are no longer managed by spring container. Normally objects managed by spring container can only be wired automatically. By default, the Autowired references in new() created classes will not be autowired.
The issue can fix in two ways
http://seniorjava.wordpress.com/2013/04/03/spring-configurable-magic/ (Spring - #Configurable)
OR
http://sujitpal.blogspot.in/2007/03/accessing-spring-beans-from-legacy-code.html (share the app context through static methods. This has side effects on unit testing.)

XSLT ClassCastException in WebSphere when Spring tries to create an AnnotationMethodHandlerAdapter

When starting WebSphere, I get this exception:
Could not instantiate bean class [org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter]:
Constructor threw exception; nested exception is java.lang.ClassCastException:
com.ibm.xtq.xslt.jaxp.compiler.TransformerFactoryImpl incompatible with
javax.xml.transform.TransformerFactory
Caused by: java.lang.ClassCastException: com.ibm.xtq.xslt.jaxp.compiler.TransformerFactoryImpl
incompatible with javax.xml.transform.TransformerFactory
at javax.xml.transform.TransformerFactory.newInstance(Unknown Source)
at org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter.<init>(AbstractXmlHttpMessageConverter.java:47)
at org.springframework.http.converter.xml.SourceHttpMessageConverter.<init>(SourceHttpMessageConverter.java:45)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.<init>(AnnotationMethodHandlerAdapter.java:197)
This doesn't seem have any impact on any beans in my applicationContext.xml but it's still odd. For me, this looks as if IBM classes are leaking into my application.
How can I fix this? I already set the option "Access to internal server classes" to "Restrict".
It was indeed a class-loading issue, however this cannot be solved by changing class-loader settings.
The problem was that the xml-apis and javax.xml jars were being imported over some maven dependencies.
Since we already set the class loader policies for the application to PARENT_LAST, the javax.xml.transform.TransformerFactory was being loaded from the WebApp-Class loader from our jar files.
However its implementation 'com.ibm.xtq.xslt.jaxp.compiler.TransformerFactoryImpl' was coming from the server class loader, this one was linked to the javax.xml.transform.TransformerFactory provided by the JDK/JRE.
Since the classes were loaded from different sources a ClassCastException was thrown.
Removing all dependencies to xml-apis / xerces / javax.xml jars solved the problem.
Since these APIs are now part of the JDK they no longer need to be imported.
... and if you wonder why I know so much about this issue: I work together with Aaron. ;)
I can't speak for Restrict as I have no personal experience with it,But I think the problem is more to do with IBM Class Loader. The class you are referring to is part of IBM Java implementation of TransformerFactory, I think you can try one of the following to solve this issue on hand
Either change the server class loader policy to PARENT_LAST (This way class loader will find the class from application's local class path, before going to up the chain all the way to java run time)
The other option would be look at the jaxp.properties file, I think it is located in (was_root\java\jre\lib), I only read about this option never actually used it
Why do you say IBM classes are leaking into your application?
The TransformerFactory is asked to create a newInstance. It follows a sequence of steps to determine which TransformerFactory to use. If none of the config is specified, it simply chooses to use the default factory.
Here is the javadoc for TransformerFactory:
http://download.oracle.com/javase/1.5.0/docs/api/javax/xml/transform/TransformerFactory.html#newInstance()
What is the OS ? Is that AIX?
http://www.ibm.com/developerworks/java/jdk/aix/j664/sdkguide.aix64.html
Looking at this doc (link above) for AIX it tells me that this is the default Impl:
javax.xml.transform.TransformerFactory
Selects the XSLT processor. Possible values are:
com.ibm.xtq.xslt.jaxp.compiler.TransformerFactoryImpl
Use the XL TXE-J compiler. This value is the default.
Post back additional information so that we can try and troubleshoot this.
HTH
Manglu

Resources