Why error No suitable driver found for jdbc:h2 - java

When I debug my Mule application i have error:
org.springframework.dao.DataAccessResourceFailureException: Error retrieving database metadata; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: No suitable driver found for jdbc:h2:~/test
my java code:
SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate.getDataSource()).withProcedureName("my_procedure_name").withSchemaName("my_schema");
...
call.execute(in)
my aaplicationContext:
<bean id="dataSource2"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db2.driver}" />
<property name="url" value="${db2.url}" />
<property name="username" value="${db2.user}" />
<property name="password" value="${db2.password}" />
</bean>
my app_name.properties:
db2.url=jdbc:h2:~/test
db2.driver=org.h2.Driver
db2.user=sa
db2.password=
my pom:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
my classpath:
<classpathentry kind="var" path="M2_REPO/com/h2database/h2/1.4.200/h2-1.4.200.jar"/>
log info after run application:
INFO org.springframework.jdbc.datasource.DriverManagerDataSource - Loaded JDBC driver: org.h2.Driver
Also i put h2-1.4.200.jar (when I starting my application from AnypointStudio) to:
c:\...\plugins\org.mule.tooling.server.3.9.0_6.4.0.201908221250\mule\lib\user\
and:
c:\...\plugins\org.mule.tooling.server.3.9.0_6.4.0.201908221250\mule\lib\boot\
and:
c:\...\plugins\org.mule.tooling.server.3.9.0_6.4.0.201908221250\mule\lib\mule\
and when I run application from mule server h2-1.4.200.jar, I put here:
..\mule-standalone-3.9.0\lib\boot
and
..\mule-standalone-3.9.0\lib\user
and:
..\mule-standalone-3.9.0\lib\mule
why application driver h2 not found ? what's the problem ?
Thanks.

You are mixing 3 different ways of managing the JDBC driver dependency, and also duplicating the library in the runtimes. That also makes it more difficult to understand the problem, and to deploy an application.
Let's start with Maven. It looks like you are using the right dependency in the pom, as long as it is in the section.
If the project is using Maven, there should not be any need to look into , unless it is out of sync with Maven. You should not change the class path manually, or edit the build path in Anypoint Studio. These are part of Studio/Eclipse .classpath files and should be left alone. Be sure to update the project so Studio regenerates the classpath.
About MULE_HOME\lib\boot, MULE_HOME\lib\user, MULE_HOME\lib\mule (either in Studio or standalone), you should not put the library in there. The Maven dependency is enough and you are duplicating the versions. Even if you can share a library in lib\user, it is not recommended. It makes more difficult to replicate sanely a deployment and again, there is no need for the JDBC driver. You should not put anything at all in lib\boot nor lib\mule nor the other subdirectories of lib. These are reserved for the runtime.
Try removing all those extras first and see what happens with a clean deployment.
Update:
Once the libraries are cleaned up, take into account that the Spring class may have some classloading issues itself. It is almost always better to use a datasource pool implementation. There are several to choose, like c3p0, dbcp, and others.
One example with c3p0:
<spring:bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<spring:property name="driverClass" value="${JDBC.driver}"/>
<spring:property name="jdbcUrl" value="${JDBC.URL}"/>
<spring:property name="user" value="${JDBC.user}"/>
<spring:property name="password" value="${JDBC.password}"/>
<spring:property name="minPoolSize" value="5"/>
<spring:property name="maxPoolSize" value="20"/>
</spring:bean>
See https://help.mulesoft.com/s/article/Spring-based-datasources for more examples.

Related

Getting IgniteCheckedException: Default Ignite instance has already been started exception when enabling Persistence on single Node

I am deploying an application where I need to maintain some data in Ignite cache. I used in memory Ignite cache. Here is the Ignite configuration I have used:
<property name="cacheConfiguration">
<list>
<bean
class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="IGNITE_DATA" />
<property name="cacheMode" value="PARTITIONED" />
<property name="atomicityMode" value="ATOMIC" />
<property name="writeSync"
value="PRIMARY_SYNC" />
<property name="backups"
value="${IGNITE_CACHE_BACKUPS}" />
</bean>
</list>
</property>
Now when I deployed multiple instances of my application and stored data in Ignite cache. Its shared among all the application instances.
Even if any any instance goes down and comes up after sometime it has the latest data via Ignite cache sync.
But issue occurs when all the application instances go down. When they come up data is gone since it was not persisted. For persistence I used dataStorageConfiguration property and enabled the persistence. Here is the change I added to Ignite configuration:
<property name="dataStorageConfiguration">
<bean
class="org.apache.ignite.configuration.DataStorageConfiguration">
<!-- Enabling Apache Ignite Persistent Store. -->
<property name="defaultDataRegionConfiguration">
<bean
class="org.apache.ignite.configuration.DataRegionConfiguration">
<property name="persistenceEnabled" value="true" />
</bean>
</property>
<!-- Changing Write Ahead Log Mode. -->
<property name="storagePath" value="${IGNITE_BC_STORE_PATH}"/>
<property name="walMode" value="LOG_ONLY" />
</bean>
</property>
Now when I deploy my application and I try and start Ignite from Java code as mentioned below:
log.info("Initializing IGNITE...");
ignite = Ignition.start(getClass().getResource(CONF_FILE));
I get an exception every time stating the default instance has already started.Tried several things but didn't work. Even if I remove the CacheConfiguration from Ignite Configuration and just keep dataStorageConfiguration I still getting the same error. Error is :
Caused by: class org.apache.ignite.IgniteCheckedException: Default Ignite instance has already been started.
at org.apache.ignite.internal.IgnitionEx.start0(IgnitionEx.java:1141)
at org.apache.ignite.internal.IgnitionEx.startConfigurations(IgnitionEx.java:1076)
at org.apache.ignite.internal.IgnitionEx.start(IgnitionEx.java:962)
at org.apache.ignite.internal.IgnitionEx.start(IgnitionEx.java:881)
at org.apache.ignite.Ignition.start(Ignition.java:373)
Normally this error comes when we try and run multiple Ignite nodes under same JVM but here I am running single node per JVM. Then also getting the error.
Please do correct me if I am wrong.
Any help here will be appreciated.
Most probably, you have more than one IgniteConfiguration bean in your config file. If one configuration bean extends another one, then make sure, that the parent is abstract.
I have resolved the issue. Seems like the issue was not woth the Ignite configuration but was with Spring Framework configuration.
I was creating the bean for the Ignite class using the lazy-init=true. I switched that to the eager-init and that resolved my issue.
Not sure how exactly it solved this but it worked at least in my case.

How do I add JDBC drivers and configure JDBC Resources in Payara Micro?

What are my options to set up JDBC drivers and resources when using Java EE Payara Micro?
This method combines answers from Mike and Adam Bien via tainos. It involves making a new domain.xml, which is a Payara config file. No application modification is needed if it worked with full Payara. The example below is for PostgreSQL JDBC.
Open payara-micro.jar with an archive manager and extract the file /microdomain.xml.
Open microdomain.xml in a text editor.
If your application was already deployed to a full Payara, you can copy-paste the changes below from the full Payara's domain.xml.
Add right above the line containing </resources>, using your dbname, dbuser, dbpassword, hostname:port and poolname:
<jdbc-connection-pool connection-validation-method="auto-commit" driver-classname="org.postgresql.Driver" res-type="java.sql.Driver" name="poolname" is-connection-validation-required="true" connection-creation-retry-attempts="3" validate-atmost-once-period-in-seconds="60">
<property name="URL" value="jdbc:postgresql://localhost:5432/dbname"></property>
<property name="user" value="dbuser"></property>
<property name="password" value="dbpassword"></property>
</jdbc-connection-pool>
<jdbc-resource pool-name="poolname" jndi-name="jdbc/poolname"></jdbc-resource>
Add right above the line containing </server>:
<resource-ref ref="jdbc/poolname"></resource-ref>
Save and close the text editor.
Start Payara micro from command line, using your paths and filenames. Linux syntax:
java -cp "/opt/jdbc/postgresql.jar:/opt/payara/micro.jar" fish.payara.micro.PayaraMicro --deploy webapp.war --domainConfig microdomain.xml
Add the datasource definition to your web.xml and then add the jar file for the JDBC jar into your WEB-INF/lib. Then deploy the war file as usual to Payara Micro.
<data-source>
<name>java:global/ExampleDataSource</name>
<class-name>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</class-name>
<server-name>localhost</server-name>
<port-number>3306</port-number>
<database-name>mysql</database-name>
<user>root</user>
<password>root</password>
<!-- Example of how to use a Payara specific custom connection pool setting -->
<property>
<name>fish.payara.sql-trace-listeners</name>
<value>com.sun.gjc.util.SQLTraceLogger</value>
</property>
</data-source>
There is a complete example of how to do this on the Payara Examples GitHub repository. See Datasource example on Payara GitHub
You can configure JDBC in a normal domain.xml and supply that to Payara. If you're unsure, you can always take an existing domain.xml and use the JDBC configuration from that.
Payara Micro has a few command line options, one of which allows you to specify an alternative domain.xml file:
java -jar payara-micro.jar --deploy myApp.war --domainConfig mydomain.xml
If you're bootstrapping Payara Micro programmatically, you would use:
setAlternateDomainXML(File alternateDomainXML)
As the accepted answer didn't work for me a figured a different and slightly easier way. You still rely on the custom domain.xml, but the startup command can be simplified:
java -jar /opt/payara/payara-micro.jar --deploy webapp.war --domainConfig domain.xml --addJars /opt/mysql-connector-java-5.1.40-bin.jar
This call doesn't require you to know the Main class.
Adam Bien answered this question in his 19th Airhacks video.
My take, When used with custom resources is best used as an embedded server, in the main we configure the JDBC resources and with maven dependencies we include the needed drivers inside the jar or war files.
One of options is glassfish-resources.xml
<!-- db1 -->
<jdbc-connection-pool
datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" name="db1"
res-type="javax.sql.DataSource"
steady-pool-size="1"
is-connection-validation-required="true"
connection-validation-method="meta-data"
max-pool-size="10">
<property name="password" value="icoder_pwd"/>
<property name="user" value="icoder_user"/>
<property name="databaseName" value="icoder_db"/>
<property name="serverName" value="localhost"/>
<property name="portNumber" value="3310"/>
<property name="zeroDateTimeBehavior" value="convertToNull"/>
</jdbc-connection-pool>
<jdbc-resource pool-name="db1" jndi-name="jdbc/db1"/>
<!-- db2 -->
<jdbc-connection-pool
datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" name="db2"
res-type="javax.sql.DataSource"
steady-pool-size="1"
is-connection-validation-required="true"
connection-validation-method="meta-data"
max-pool-size="10">
<property name="password" value="icoder_pwd"/>
<property name="user" value="icoder_user"/>
<property name="databaseName" value="icoder_db"/>
<property name="serverName" value="localhost"/>
<property name="portNumber" value="3311"/>
<property name="zeroDateTimeBehavior" value="convertToNull"/>
</jdbc-connection-pool>
<jdbc-resource pool-name="db2" jndi-name="jdbc/db2"/>
</resources>
Complete example with entity manager implementation you can find:
https://github.com/igorzg/payara-micro-jpa-multi-tenancy

How to configure Connection Pool for Java Web Project?

I've been doing a research on connection pool with JDBC api and classes. But still I don't know how to configure a Connection Pool class for a java web project. As you may know, the Connection Pool is a Singleton Class that encapsulates the JDBC apis. But the Connection Class is started once when the web project is deployed on Tomcat Server, I wonder if there's something needed to be done with Web.xml configuration file, to let Tomcat Server load the Connection Pool Class.
Thank you very much for your time!
There a many ways of doing this. JNDI is one way - but it is not so "user friendly" in tomcat. The datasource also can be configured in Spring. For e.g.:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
The most simplest way of doing this is to create a ServletContextListener class, create your datasource and put it into ServletContext so that the same instance could be retrieved from ServletContext in your project.
See my answer here how to create ServletContextListener.
See also:
How to use JNDI DataSource provided by Tomcat in Spring?

Different persistence.xml properies for test run / JPA Fixtures

I develop some Java EE/Spring web-app. I use JPA 2.0 - Hibernate. For integration tests I need to use different database. Those tests require Jetty to run application, but I managed to override web.xml for such run, there I can modify my Spring context files, it's ok.
But I need each time a clean database (and load some data into it).
As my database name and address are configured in sprig context I just switched them as I described above - but how can I change some of my persistence.xml properies for this tests only to have database drop and recreated?
I tried to make another persistence.xml in /src/test/resources/META-INF (and checked that test-classes are first in classpath) but it is not loaded and only the 'master' version is used (from /src/main/resources/META-INF). Any help?
With spring you usually define your data source as a spring bean. The database url and credentials are usually included form an external file, for example application.properties.
If you put a new applicaiton.properties in src/test/resources it will work. See also here.
You can define org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager :
<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>/path/to/my/test-persistence.xml</value>
</list>
</property>
<property name="dataSources">
<map>
<entry key="dataSource" value-ref="dataSource"/>
</map>
</property>
<!-- if no datasource is specified, use this one -->
<property name="defaultDataSource" ref="dataSource"/>
</bean>
Then, link it to your entityManagerFactory :
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
...
...
<property name="persistenceUnitManager" ref="pum"/>
</bean>
I used this to make my own persistence.xml linked to a HSQL in-memory db, preloaded with DBUnit (using hibernate.hbm2ddl.auto=create-drop).
It Works perfectly.

instantiating spring bean outside the container (for testing)

I have following in my applicaionContext.xml
<bean id="IbatisDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#123.210.85.56:1522:ORCL"/>
<property name="username" value="mydb"/>
<property name="password" value="mydbpwd"/>
</bean>
<bean id="myMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="classpath:sql-map-config-oracle.xml"/>
<property name="dataSource" ref="IbatisDataSource"/>
</bean>
then in my code I have:
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
SqlMapClient sqlclient = (SqlMapClient) ctx.getBean("myMapClient");
doing this gives me the following error:
Error creating bean with name
'myMapClient' defined in class
path resource
[applicationContext.xml]: Invocation
of init method failed; nested
exception is
java.lang.NoClassDefFoundError:
com/iplanet/ias/admin/common/ASException
I don't understand why is it looking for that class? I am trying to do everything outside the container. So it should not even be looking for that class...but nonetheless just to make it work I tried looking for class called ASException so I could put it on the classpath but no where can I find ASException class.
Any pointers?
Images of stack trace and my compile test / run test libs
Edit
Solution:
Even though I thought everything was outside the container...there was ONE thing that was not outside the container.
Notice the property configLocation:
<property name="configLocation" value="classpath:sql-map-config-oracle.xml"/>
actual content of sql-map-config-oracle.xml is
<sqlMapConfig>
<settings enhancementEnabled="true" useStatementNamespaces="true" />
<transactionManager type="JDBC">
<dataSource type="JNDI">
<property name="DataSource" value="my/jndi/mydb" />
</dataSource>
</transactionManager>
<sqlMap resource="somemapping.xml"/>
</sqlMapConfig>
JNDI stuff does not need to be there!
sql-map-config-oracle.xml should simply be:
<sqlMapConfig>
<settings enhancementEnabled="true" useStatementNamespaces="true" />
<sqlMap resource="somemapping.xml"/>
</sqlMapConfig>
You definitely have a runtime dependency issue as #Cletus said org.springframework.orm.ibatis.SqlMapClientFactoryBean was compiled with com.iplanet.ias.admin.common.ASException but now you don't have it in your classpath -- Spring can't find it. You should Look at the source for SqlMapClientFactoryBean to see where ASException is called -- Spring should have a dist with all it's dependencies in it, you can also look in there when doing your investigation.
This class was found during compilation but not during running:
com/iplanet/ias/admin/common/ASException
So when you're running the program, it can't seem to find this class, which belongs to the Sun app or portal server that you're using. In short: it's a classpath error.

Categories

Resources