Configuring Mysql DataSource with IBM WebSphere Application Server Liberty Profile - java

I have a spring mvc application which i am deploying on IBM WebSphere Application Server Liberty Profile, the application is supposed to access a mysql database server that is hosted locally. I have added the datasource configuration as follows in the sever.xml file
<dataSource id="springdb" jndiName="jdbc/springdb">
<jdbcDriver javax.sql.XADataSource="com.mysql.cj.jdbc.Driver" libraryRef="mysqlJDBCLib"/>
<properties databaseName="spring_db" password="**********" portNumber="3306" serverName="localhost" user="root"/>
</dataSource>
<library id="mysqlJDBCLib">
<fileset dir="/opt/IBM/WebSphere/Liberty_16.0.0.4/usr/shared/resources/mysql" includes="mysql-connector-java-6.0.6.jar"/>
</library>
I am getting the following stack trace
Caused by: java.lang.RuntimeException: java.sql.SQLNonTransientException: DSRA4000E: A valid JDBC driver implementation class was not found for the jdbcDriver dataSource[springdb]/jdbcDriver[default-0] using the library mysqlJDBCLib. [/opt/IBM/WebSphere/Liberty_16.0.0.4/usr/shared/resources/mysql/mysql-connector-java-6.0.6.jar]
at com.ibm.ws.resource.internal.ResourceFactoryTrackerData$1.getService(ResourceFactoryTrackerData.java:123)
... 77 more
Caused by: java.sql.SQLNonTransientException: DSRA4000E: A valid JDBC driver implementation class was not found for the jdbcDriver dataSource[springdb]/jdbcDriver[default-0] using the library mysqlJDBCLib. [/opt/IBM/WebSphere/Liberty_16.0.0.4/usr/shared/resources/mysql/mysql-connector-java-6.0.6.jar]
at com.ibm.ws.jdbc.internal.JDBCDriverService.classNotFound(JDBCDriverService.java:196)
... 77 more
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
at com.ibm.ws.classloading.internal.AppClassLoader.findClassCommonLibraryClassLoaders(AppClassLoader.java:499)
... 77 more
I have tried the following
Replacing com.mysql.cj.jdbc.Driver with com.mysql.jdbc.Driver and string got the same error
Replacing javax.sql.XADataSource with javax.sql.DataSource and still got the same error
Replacing javax.sql.XADataSource with javax.sql.MysqlConnectionPoolDataSource, same error
Switching out the mysql connector jar from mysql-connector-java-6.0.6.jar to mysql-connector-java-5.1.45-bin.jar, still same error (both the jars are there in the specified file path)

Background info about datasource config:
For all datasources (except for id="DefaultDataSource") the type of DataSource is selected in the following priority:
Use the type class configured on the <dataSource> element, if configured
javax.sql.ConnectionPoolDataSource This option is active in your case
javax.sql.DataSource
javax.sql.XADataSource
(According to Configuring relational database connectivity in Liberty)
If no class is defined for a type, then the next lowest priority will be checked.
By default, Liberty will scan for use the following priority for locating data source implementation class names:
Use the corresponding value configured on the <jdbcDriver> element
Use the default classes for a <properties.DRIVER_TYPE> element. Note that only some JDBC drivers have their own element types. For JDBC drivers that do not have their own properties element (such as MySQL) use the generic <properties> element
Based on the JDBC driver jar name, Liberty will try to guess the implementation class name. This option is active in your case
Reason why your configuration is not working
You've configured your <jdbcDriver> element to say "Use this specific class for XADataSource's", however, the <dataSource> element you've configured is not attempting to create an XADataSource. Using the priority order mentioned above, it will first try to create a ConnectionPoolDataSource (which Liberty has internally mapped to com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource.
To fix the problem:
Specify <dataSource .. type="javax.sql.XADataSource"> in your configuration so that Liberty will try to create an XADataSource instead of a ConnectionPoolDataSource. Then when it tries to create the XADataSource it will look at the class name you've configured on the <jdbcDriver> element.
Specify MySQL's XADataSource class name for the javax.sql.XADataSource property (which is com.mysql.cj.jdbc.MysqlXADataSource) instead of their java.sql.Driver implementation class name.
So your final configuration would look like this:
<dataSource id="springdb" jndiName="jdbc/springdb" type="javax.sql.XADataSource">
<jdbcDriver javax.sql.XADataSource="com.mysql.cj.jdbc.MysqlXADataSource" libraryRef="mysqlJDBCLib"/>
<properties databaseName="spring_db" password="**********" portNumber="3306" serverName="localhost" user="root"/>
</dataSource>
<library id="mysqlJDBCLib">
<fileset dir="/opt/IBM/WebSphere/Liberty_16.0.0.4/usr/shared/resources/mysql" includes="mysql-connector-java-6.0.6.jar"/>
</library>

If you don't specify the type attribute in the dataSource config element, Liberty will try to infer the datasource class to load based on the driver jar filename. In your example, it is incorrectly inferring implementation class names based on a previous mySQL driver. It appears that mySQL has changed the package names of their implementations for DataSource, ConnectionPoolDataSource and XADataSource. I'll open an git issue for this. In the meantime, you can simply specify the type of datasource to create using the type attribute of the dataSource config element and then update your jdbcDriver config element with javax.sql.DataSource="com.mysql.cj.jdbc.MysqlDataSource" to point to the proper mysql driver class. If instead you need a conn pool or XA datasource instead, just update the type attribute of dataSource to identify the type and update jdbcDriver with the driver class impl.

Related

H2 in memory database not working after update to SpringBoot 2.4.0

I have an SpringBoot application with integrationtests utilising an H2 inmemory database. The tests work, if I use SpringBoot in versino 2.3.4.RELEASE. They fail if I upgrade to 2.4.0 with the following error:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: Invocation of init method failed; nested exception is java.lang.RuntimeException: Driver com.microsoft.sqlserver.jdbc.SQLServerDriver claims to not accept jdbcUrl, jdbc:h2:mem:integrationTestDB;DB_CLOSE_DELAY=-1;MODE=MSSQLServer;INIT=CREATE SCHEMA IF NOT EXISTS dbo\;SET SCHEMA dbo
Caused by: java.lang.RuntimeException: Driver com.microsoft.sqlserver.jdbc.SQLServerDriver claims to not accept jdbcUrl, jdbc:h2:mem:integrationTestDB;DB_CLOSE_DELAY=-1;MODE=MSSQLServer;INIT=CREATE SCHEMA IF NOT EXISTS dbo\;SET SCHEMA dbo
Here is my integration-test.properties, that is used by the tests:
spring.datasource.url=jdbc:h2:mem:integrationTestDB;\
DB_CLOSE_DELAY=-1;\
MODE=MSSQLServer;\
INIT=CREATE SCHEMA IF NOT EXISTS dbo\\;SET SCHEMA dbo
spring.datasource.driver=org.h2.Driver
spring.datasource.hikari.driver-class-name=org.h2.Driver
hibernate.dialect=org.hibernate.dialect.SQLServerDialect
hibernate.hbm2ddl.auto=none
spring.datasource.username=sa
spring.datasource.password=
spring.liquibase.user=sa
spring.liquibase.password=
The version of H2 is 1.4.200.
The difference between success and failure is the SpringBoot version in the parent element of the pom:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
</parent>
The liquibase version changed from 3.8.9 to 3.10.3. I configured it to stay at 3.8.9 but that didn't help.
I read the release notes and found the part about the embedded database detection: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.4-Release-Notes#embedded-database-detection
But adding
spring.datasource.initialization-mode=always
to the properties didn't help either.
I remember that it took some time to find the right datasource url last time, but I can't find any new clues with google.
Can you give me a hint, what causes this problem?
Kind regards,
Ulrich
Your properties contain a mixture of H2 and SQL Server configuration. For example, you've configured an H2 JDBC URL for the DataSource but configured Hibernate to use SQLServerDialect. The exception shows that SQL Server's JDBC driver is being used when trying to initialise Liquibase. It looks to me like you're trying to use H2 in your integration tests, replacing SQL Server that's used when your app's deployed.
There's a new spring.liquibase.driver-class-name property in 2.4.0. When not set, it falls back to using spring.datasource.driver-class-name. There's no spring.datasource.driver property so try replacing the following two lines:
spring.datasource.driver=org.h2.Driver
spring.datasource.hikari.driver-class-name=org.h2.Driver
with the following line:
spring.datasource.driver-class-name=org.h2.Driver

WSJDBCConnection does not wrap objects of type Oracle jdbc Connection

I am using Websphere liberty server to run my application and I need to use ArrayDescriptor for passing arrays to the oracle stored procedure. I get an exception while unwrapping the connection. I have checked the connection meta data driver information as well and it is showing me oracle.jdbc driver. The code fails at connection unwrapping line.
Connection conn = this.getDataSource().getConnection();
OracleConnection oracleConn = conn.unwrap(oracle.jdbc.OracleConnection.class);
Exception message: java.sql.SQLException: DSRA9122E:
com.ibm.ws.rsadapter.jdbc.v41.WSJdbc41Connection#120edaf does not wrap
any objects of type oracle.jdbc.OracleConnection.
I have added class loader reference for my application in the server.xml as well but that didn't help.
My server.xml looks like :
<dataSource id="datasource" jndiName="jdbc/XXXXXX"
type="javax.sql.XADataSource">
<jdbcDriver libraryRef="ordLib"/>
<properties.oracle databaseName="XXXX" driverType="thin" password="XXXXXX"
portNumber="XXXXXX" serverName="XXXXXX" serviceName="XXXXXX" url="XXXXXX"
user="XXXXXX"/>
</dataSource>
<webApplication id="NAExtractWeb" location="NAExtractWeb.war"
name="NAExtractWeb">
<classloader commonLibraryRef="ordLib"></classloader>
</webApplication>
<library id="ordLib">
<fileset dir="C:\lib" id="fileset" includes="ojdbc6-11.2.0.4.jar"/>
</library>
Also I use this unwrap function in one of my dependent project jar and I have ojdbc dependency(maven) added in my dependent project. Will that affect the unwrapping step?
Here is the method which will get the data source:
public DataSource getDataSource(String dsName) throws BatchException {
try {
return (DataSource) new InitialContext().lookup(dsName);
} catch (Exception e) {
//Code to handle
}
}
Here is the full stack trace:
[6/19/18 17:20:29:340 IST] [process partition0] com.ibm.ws.batch.JobLogger CWWKY0030I: An exception occurred while running the step process.
com.ibm.jbatch.container.exception.BatchContainerRuntimeException: Failure in Read-Process-Write Loop
at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.invokeChunk(ChunkStepControllerImpl.java:704)
at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.invokeCoreStep(ChunkStepControllerImpl.java:795)
at com.ibm.jbatch.container.controller.impl.BaseStepControllerImpl.execute(BaseStepControllerImpl.java:293)
at com.ibm.jbatch.container.controller.impl.ExecutionTransitioner.doExecutionLoop(ExecutionTransitioner.java:118)
at com.ibm.jbatch.container.controller.impl.WorkUnitThreadControllerImpl.executeCoreTransitionLoop(WorkUnitThreadControllerImpl.java:93)
at com.ibm.jbatch.container.controller.impl.WorkUnitThreadControllerImpl.executeWorkUnit(WorkUnitThreadControllerImpl.java:155)
at com.ibm.jbatch.container.controller.impl.WorkUnitThreadControllerImpl$AbstractControllerHelper.runExecutionOnThread(WorkUnitThreadControllerImpl.java:480)
at com.ibm.jbatch.container.controller.impl.WorkUnitThreadControllerImpl.runExecutionOnThread(WorkUnitThreadControllerImpl.java:89)
at com.ibm.jbatch.container.util.BatchWorkUnit.run(BatchWorkUnit.java:117)
at com.ibm.ws.context.service.serializable.ContextualRunnable.run(ContextualRunnable.java:79)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: com.ibm.jbatch.container.exception.BatchContainerRuntimeException: java.sql.SQLException: DSRA9122E: com.ibm.ws.rsadapter.jdbc.v41.WSJdbc41Connection#73c25e77 does not wrap any objects of type oracle.jdbc.OracleConnection.
at com.ibm.jbatch.container.artifact.proxy.ItemWriterProxy.open(ItemWriterProxy.java:67)
at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.openReaderAndWriter(ChunkStepControllerImpl.java:954)
at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.invokeChunk(ChunkStepControllerImpl.java:599)
... 14 more
Caused by: java.sql.SQLException: DSRA9122E: com.ibm.ws.rsadapter.jdbc.v41.WSJdbc41Connection#73c25e77 does not wrap any objects of type oracle.jdbc.OracleConnection.
at com.ibm.ws.rsadapter.jdbc.WSJdbcWrapper.unwrap(WSJdbcWrapper.java:459)
at com.fmr.nfiws.batch.writer.DBWriter.open(DBWriter.java:149)
at com.ibm.jbatch.container.artifact.proxy.ItemWriterProxy.open(ItemWriterProxy.java:64)
... 16 more
I just tested this on WebSphere Liberty and the following code worked for me:
#Resource(lookup = "jdbc/oracle")
private DataSource ds;
// ...
Connection conn = ds.getConnection();
OracleConnection oracleConn = conn.unwrap(oracle.jdbc.OracleConnection.class);
My server.xml looks like this:
<dataSource jndiName="jdbc/oracle">
<jdbcDriver libraryRef="oracleLib"/>
<properties.oracle URL="${jdbc.URL}" user="${jdbc.user}" password="${jdbc.password}"/>
</dataSource>
<library id="oracleLib">
<fileset dir="${server.config.dir}/oracle"/>
</library>
<application location="myApp.war" >
<classloader commonLibraryRef="oracleLib"/>
</application>
The important thing to note here is the use of commonLibraryRef on the <classloader> element. If you use privateLibraryRef it will not work because the app and server-defined datasource will use isolated classloaders to load the Oracle JDBC classes.
If this answer isn't helpful to you, please update your question with your server.xml configuration, and also how you are obtaining an instance of your DataSource.
If someone has this problem here is my solution.
My mistake was that I was deploying my application to the dropins folder and if you define an application/webApplication in your server.xml it is ignored. I deployed it somewhere else, set this new location to the application tag and also added the <classloader> in server.xml, left the ojdbc jar as provided in pom.xml and it works now.
But still I had a problem when I was running the application locally, because the ojdbc jar was provided in pom.xml.
My solution was to use reflection to get the system class loader and load the jar at runtime for the local profile.
Hope this helps someone.
I tried the same thing in my local machine, but not worked because of same ojdbc jar available in the liberty run time server path. After removing its works fine.
LibertyRuntime(In project explorer)->
servers(choose the deployed server)->
apps->you could see application-name.war.xml(Please remove the ojdbc jar from the xml).
Make sure the jar is not available in the xml file
Finally start the server, It will work.

Connection with Sybase

I am new to Sybase ,I'm developing a web application with sybase and jboss, my app connect with the Sybase database. I have put the jconn4.jar in same directory with war file in deployments directory . My config in standalone.xml like this
<connection-url>jdbc:jtds:sybase://<myserver>:<myport>/<mydb></connection-url>
<driver-class>com.sybase.jdbc4.jdbc.SybDriver</driver-class>
<!--<driver-class>net.sourceforge.jtds.jdbc.Driver</driver-class> -->
<driver>jconn4.jar</driver>
and when i use com.sybase.jdbc4.jdbc.SybDriver got the error message
javax.resource.ResourceException: Wrong driver class [class com.sybase.jdbc4.jdbc.SybDriver] for this connection URL [jdbc:jtds:sybase://<myhost>:<myport>/<mydb>
...
when i use net.sourceforge.jtds.jdbc.Driver i got the message
java.lang.ClassNotFoundException: net.sourceforge.jtds.jdbc.Driver from [Module "deployment.jconn4.jar:main" from Service Module Loader]
I don't know what driver-class suitable for driver class jconn4.jar
You are using the driver url of the open source jTDS driver, but you are trying to use the Sybase driver. Use the right JDBC url for the Sybase driver: Check the documentation included with the Sybase driver for details (I can't be more specific because the Sybase documentation is usually hard to find online without access to the support portal). Or switch to jTDS, in which case you need to deploy it as a module to JBoss and reference the right driver module in the config.

How to set up jndi.properties for DataStore?

I'm struggling to set connect a Java program to MySQL using JPA/Hibernate.
I'm currently getting the following error when I try to call createEntityManagerFactory():
[main] ERROR org.hibernate.connection.DatasourceConnectionProvider - Could not find datasource: java:jdbc/myDataDS
javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:325)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at org.hibernate.connection.DatasourceConnectionProvider.configure(DatasourceConnectionProvider.java:75)
Googling seems to indicate that I need a jndi.properties file in META-INF in my classpath, but I can't seem to find any information about what that file should contain in my case.
Edit: I'm running this stand-alone, for the time being.
A jndi.properties file should be at the root of the classpath and typically contains the URL of the JNDI server and the initial context factory to use. For example, with JBoss:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
But, when using Hibernate, you should actually declare these properties in the hibernate.cfg.xml. For example, with WebLogic:
<property name="jndi.class">weblogic.jndi.WLInitialContextFactory</property>
<property name="jndi.url">t3://127.0.0.1:7001</property>

problem configure JBoss to work with JNDI

I am trying to bind connection to the DB using JNDI in my application that runs on JBoss. I did the following:
I created the datasource file oracle-ds.xml filled it with the relevant xml elements:
<datasources>
<local-tx-datasource>
<jndi-name>bilby</jndi-name>
...
</local-tx-datasource>
</datasources>
and put it in the folder \server\default\deploy
Added the relevant oracle jar file
than in my application I performed:
JndiObjectFactoryBean factory = new
JndiObjectFactoryBean();
factory.setJndiName("bilby");
try{
factory.afterPropertiesSet();
dataSource = factory.getObject();
}
catch(NamingException ne) {
ne.printStackTrace();
}
and this cause the error:
javax.naming.NameNotFoundException:
bilby not bound
then in the output after this error occured I saw the line:
18:37:56,560 INFO
[ConnectionFactoryBindingService]
Bound ConnectionManager 'jb
oss.jca:service=DataSourceBinding,name=bilby'
to JNDI name 'java:bilby'
So what is my configuration problem? I think that it may be that JBoss first loads and runs the .war file of my application and only then it loads the oracle-ds.xml that contain my data-source definition.
The problem is that they are both located in the same folder.
Is there a way to define priority of loading them, or maybe this is not the problem at all.
Any idea?
You should use such construction to call Datasource: java:bilby.
You can read more about that here:
Naming and Directory (JNDI) - JBOSS jndi Datasource: jdbc not bound
To check how the datasource is bound in the JNDI tree you should use the jmx-console
http://localhost8080/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DJNDIView
and invoke the list() method.
Datasources are registered under "jdbc". In your case "jdbc/bilby"
EDIT: That was an example that works for me without spring.
Now found this example which injects a more complete JNDI name.
<bean id="idDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/bilby" />
</bean>

Categories