Dependencies for Firebird, Jaybird and Hibernate - java

I was interested to see the performance of Firebird with Hibernate, but I can not manage to make it run correctly. I added to my pom.xml:
<dependency>
<groupId>net.sf.squirrel-sql.thirdparty-non-maven</groupId>
<artifactId>jaybird</artifactId>
<version>2.1.6</version>
</dependency>
When running it I keep getting:
java.lang.ClassNotFoundException: javax.resource.ResourceException
I tried adding all kinds of javax, javaee and others dependencies (via Maven), but I can't manage to run it. With PostgreSQL I have no issues and everything works as it is supposed to.
Running on Apache Tomcat 7.0.26.

The 'problem' is that Jaybird internally depends on the JavaEE concept of a resource-adapter and therefor requires some classes from JavaEE (specifically one that includes the javax.resource package (and subpackages). You need to include a JavaEE jar, or use
<groupId>org.firebirdsql.jdbc</groupId>
<artifactId>jaybird-jdk18</artifactId>
<version>3.0.5</version>
This one should automatically download the required dependency.
If all else fails, download the distribution from http://www.firebirdsql.org/en/jdbc-driver/ and use the connector-api-1.5.jar from the lib folder.
BTW: I hope to eliminate this dependency in Jaybird 5.
Disclaimer: I am one of the developers of Jaybird

We'll i was able to figure this out:
you can use hibernate's own connection pool
you can use commons-dbcp connection pool
you can use new tomcat7's jdbc connection pool.
Assuming you want to use 3, there are few steps you must perform, if you use firebird
Download jdk from : http://sourceforge.net/projects/firebird/files/firebird-jca-jdbc-driver/2.2.0-release-jdk16/Jaybird-2.2.0JDK_1.6.zip/download
Extract archive, copy jaybird*.jar and connector-api*.jar to /usr/share/tomcat7/lib.
Inside the connector-api jar, there is the missing class ResourceException.
WARNING: do not copy huge j2eeapi.jar instead, beacuse they contain offending classes to servlet-api.jar from tomcat
If you installed tomcat7 from tar, that's all. If you use ubuntu apt to install tomcat's package, then download original tar from tomcat's download side, extract it and copy tomcat-jdbc to wherever is you tomcat's lib folder (for ubuntu, that is /usr/share/tomcat7/lib)
That's all. Put the configuration into context.xml and that's all
<Resource
name="jdbc/SOME_NAME"
auth="Container"
type="javax.sql.DataSource"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
testWhileIdle="true"
testOnBorrow="true"
testOnReturn="false"
validationQuery="SELECT 'NOW' from RDB$DATABASE"
validationInterval="30000"
timeBetweenEvictionRunsMillis="30000"
maxActive="100"
minIdle="10"
maxWait="10000"
initialSize="10"
removeAbandonedTimeout="60"
removeAbandoned="true"
logAbandoned="true"
minEvictableIdleTimeMillis="30000"
jmxEnabled="true"
jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"
username="sysdba"
password="masterke"
driverClassName="org.firebirdsql.jdbc.FBDriver"
url="jdbc:firebirdsql:IP:ALIAS?lc_ctype=UTF-8"
/>

Related

Aspect fails with ClassCastException trying to pointcut Tomcat DataSource getConnection

I need to execute several initialization statements on each borrowed connection from a Tomcat JDBC Pool. I cannot use JDBCInterceptors because pool is shared with other applications that won't need said initilization.
I'm using Spring Boot 1.4.4, deploying on Tomcat 8.5.11, which has a ResourceLink in context.xml to a Resource in server.xml that defines the DataSource against a Oracle 11g Database. I'm accessing the DataSource via JNDI.
As per this answer https://stackoverflow.com/a/38746398 I wanted to use Spring AOP to accomplish my goal.
I have created and Aspect that works perfectly if the DataSource is defined directly in context.xml, but fails with a ClassCastException if referenced via a ResourceLink to the same definition in server.xml
The exception is:
java.lang.ClassCastException: org.apache.tomcat.jdbc.pool.DataSource cannot be cast to org.apache.tomcat.jdbc.pool.DataSourceProxy
at org.apache.tomcat.jdbc.pool.DataSourceProxy$$FastClassBySpringCGLIB$$26808f96.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)
at org.apache.tomcat.jdbc.pool.DataSource$$EnhancerBySpringCGLIB$$17f85659.getConnection(<generated>)
My Aspect class:
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class DataSourceAspect {
private static final Logger LOG = LoggerFactory.getLogger(DataSourceAspect.class);
#AfterReturning(pointcut = "execution(* org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection())")
public void afterConnectionEstablished() {
LOG.info("Borrowed connection from the pool. Initializing...");
}
}
ResourceLink definition in context.xml:
<ResourceLink name="jdbc/us_j2eeCoreDS"
global="jdbc/us_j2eeCoreDS"
type="javax.sql.DataSource"/>
DataSource definition in server.xml (changed private values):
<Resource name="jdbc/us_j2eeCoreDS" type="javax.sql.DataSource"
global="jdbc/us_j2eeCoreDS"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="oracle.jdbc.OracleDriver"
username="xxx" password="xxx"
initialSize="1"
minIdle="1"
maxIdle="4" maxWaitMillis="5000"
maxActive="40"
removeAbandonedOnBorrow="true" removeAbandonedTimeout="300"
testWhileIdle="true"
validationQuery="SELECT 1 FROM DUAL"
timeBetweenEvictionRunsMillis="60000"
url="jdbc:oracle:thin:#host:port:SID"/>
As I said before, if I define the exact same DataSource in context.xml, it works flawlessly.
Any clue?
Thanks a lot.
Eventually the problem was not AOP related, but a dependency conflict.
The project is based on Spring Boot 1.4.4.RELEASE. In my build.gradle, I had the following dependency:
compile("org.springframework.boot:spring-boot-starter-data-jpa")
Being a starter, it's just a quick way to get more needed dependencies. One of the deps provided is:
org.springframework.boot:spring-boot-starter-jdbc:1.4.4.RELEASE
Which provides:
org.apache.tomcat:tomcat-jdbc:8.5.11
So as it turns out my war package ended up containing tomcat-jdbc-8.5.11.jar.
Tomcat 8.5.11 server also contained the same library, tomcat-jdbc.jar.
As the pool was server.xml defined, the library used by the pool was tomcat-jdbc.jar, but my application, having tomcat-jdbc-8.5.11.jar inside its WEB-INF/libs directory, used tomcat-jdbc-8.5.11.jar, leading to the ClassCastException. I didn't have time to dig out more and find the actual reason why it worked if the pool was defined in context.xml, but I guess it's just a case of jar loading priority.
The fix: exclude the tomcat-jdbc-8.5.11.jar from the war package, using the following gradle enchanment (just include it in your build.gradle configurations section):
configurations {
runtime.exclude module: 'tomcat-jdbc'
}
Hope this helps somebody else!

javax.naming.NameNotFoundException when trying to lookup resource declared in context.xml

I am deploying a WAR to JBoss EAP 7. In my WAR's META-INF/context.xml file I have the following:
<Context unloadDelay="500000">
<Resource name="jdbc/sybase/somedb"
auth="Container"
type="javax.sql.DataSource"
driverClassName="net.sourceforge.jtds.jdbc.Driver"
url="jdbc:jtds:sybase://localhost:12501/somedb"
username="username" password="secret"
validationQuery="select 1"
maxActive="2" maxIdle="0" maxWait="-1"/>
...
From my Java code I try to obtain the DataSource doing a:
InitialContext cxt = new InitialContext();
DataSource ds = (DataSource) cxt.lookup( "java:/comp/env/jdbc/sybase/somedb" );
The exact above code works and the name is found in the context when I deploy to Tomcat 8 but not when I deploy to JBoss EAP 7. In the latter case I get:
Caused by: javax.naming.NameNotFoundException: comp/env/jdbc/sybase/somedb -- service jboss.naming.context.java.comp.env.jdbc.sybase.somedb
at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:106)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:207)
at org.jboss.as.naming.InitialContext$DefaultInitialContext.lookup(InitialContext.java:235)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:193)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:189)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
What am I doing wrong and how can I fix the above problem?
Your META-INF/context.xml file is a Tomcat deployment descriptor (not defined by the Java EE specification) so it is not seen or parsed by JBoss EAP 7.
There are many alternatives to this including the solution to is there a standard way to define a JDBC Datasource for Java EE containers.
If you were to ask RedHat support they would likely recommend that you create the datasource using server administration tools such as the admin console or jboss-cli.sh. This decouples your application from the datasource definition so that you can specify environment specific settings (such as pool sizes and hostnames) without repackaging your WAR.file. This method also requires you to deploy the JDBC driver jar separately from your application.

How to configure datasource in wildfly 10?

I am starting introduction with wildfly learning.
I have downloaded distribution of server.
Now I am trying to configure datasource but I see following error:
Unexpected HTTP response: 500
Request
{
"address" => [
("subsystem" => "datasources"),
("data-source" => "PostgreDataSource")
],
"operation" => "test-connection-in-pool"
}
Response
Internal Server Error
{
"outcome" => "failed",
"failure-description" => "WFLYJCA0040: failed to invoke operation: WFLYJCA0042: failed to match pool. Check JndiName: java:jboss/datasources/PostgreDataSource",
"rolled-back" => true
}
My steps:
1. Created folder wildfly-10.0.0.CR2\wildfly-10.0.0.CR2\modules\org\postgres\main and copy postgresql-9.0-801.jdbc4.jar from \.m2\repository\postgresql\postgresql\9.0-801.jdbc4 there.
2.Created module.xml(inside wildfly-10.0.0.CR2\wildfly-10.0.0.CR2\modules):
with following content:
<module xmlns="urn:jboss:module:1.0" name="org.postgres">
<resources>
<resource-root path="postgresql-9.0-801.jdbc4.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.transaction.api"/>
</dependencies>
</module>
Modified standalone.xml(wildfly-10.0.0.CR2\wildfly-10.0.0.CR2\standalone\configuration) like this(sorry - I don't know how to copy xml that it can be visible for another users(full content visible here: http://collabedit.com/psk4a)):
Please help to understand what do I wrong?
Below given is driver configuration and data source creation and how to make it globally visible so that all J2EE deployments can access the particular module if needed.
1. PostGreSQL Driver Configuration
Create directory structure as below inside the modules in wildfly-8.2.0.Final\modules directory and place the mentioned files and driver jar.
Directory: wildfly-8.2.0.Final\modules\org\postgresql\main
File: module.xml
<!--<?xml version="1.0" encoding="UTF-8"?>-->
<module xmlns="urn:jboss:module:1.0" name="org.postgresql">
<resources>
<resource-root path="postgresql-9.4-1204.jdbc41.jar"/>
</resources>
<dependencies><module name="javax.api"/></dependencies>
</module>
JAR : PostGreSQL Driver: postgresql-9.4-1204.jdbc41.jar
Note : Driver version can be your choice and please ensure to reflect that version name in module.xml file.
Please note that the driver name="org.postgresql” mentioned in the module.xml file should be matching with the data source(s) configuration in the standalone.xml file.
Note: The PostGreSQL driver version should be compatible to the java version in the system.
In this example, java is 1.7 & PostGreSQL driver used is postgresql-9.4-1204.jdbc41.jar.
2. Configuring the DataSources
Datasources are configured in the standalone.xml file in the WildFly 8.2.0.Final\standalone\configuration.
As the first step configure the PostGreSQL driver reference in the standalone.xml file as below inside the tag
<driver name="postgresql" module="org.postgresql">
<datasource-class>org.postgresql.Driver</datasource-class>
<xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
</driver>
1. Add the datasource details:
Please add this inside tag
<datasource jndi-name="java:/db1" pool-name="db1" enabled="true" use-java-context="true">
<connection-url>jdbc:postgresql://localhost:5432/dbname</connection-url>
<driver>postgresql</driver>
<security>
<user-name>user_name</user-name>
<password>password</password>
</security>
</datasource>
2.make the published drivers globally visible by adding
to the section
Here it is:
<global-modules>
<module name="org.postgresql" slot="main"/>
</global-modules>
Note : Global modules is a set of JBoss Modules that will be added as dependencies to the JBoss Module of every Java EE deployment. Such dependencies allows Java EE deployments to see the classes exported by the global modules. Refer : https://docs.jboss.org/author/display/WFLY8/Subsystem+configuration
Once configured the above, please start your WildFly instance.
Problem resolved after move module.xml to wildfly-10.0.0.CR2\wildfly-10.0.0.CR2\modules\org\postgres\main
I am not 100% positive, but if I see some links around the net it may be caused by default pool settings. You might try by adding specific pool configuration settings to your datasource:
<datasource jndi-name="blabla"... >
<pool>
<min-pool-size>1</min-pool-size>
<max-pool-size>20</max-pool-size>
<prefill>true</prefill>
</pool>
</datasource>
I base that on this stackoverflow thread: WildFly jdbc connection with Oracle
where an answer links to this related JBoss forum thread: https://developer.jboss.org/thread/257721
The pool settings are mentioned in the Wildfly configuration documentation by the way. This is Wildfly 9, but I can't imagine things changed much in Wildfly 10: https://docs.jboss.org/author/display/WFLY9/DataSource+configuration
I'd like to say that I solved the problem only by using wildfly admin console (http://localhost:9990/console/). Not so spartan solution, but it works. I only pointed the JDBC driver jar from external directory and after I created a datasource. No xml by hand and no modifying wildfly's directory structure.
For java 8 + postgresql 9.5 I used postgresql-42.1.1.jar. I had problems befor only because I chose the wrong driver and database's name was wrong.
Although this topic is a bit old, I'd like to stress that the recommended way to install a datasource as a module is using the CLI 'module add' command which creates the full path for the module and the module.xml configuration file. This makes the whole process less error-prone.
module add --name=org.postgres --resources=[JDBC JAR FILE] --dependencies=javax.api,javax.transaction.api
Also, I see mentioned here the usage of global modules for datasource. This is not a common practice for JDBC drivers as global modules are meant to be used for shared libraries which are common to all applications and don't require maintenance. You might end up with an unconsistent datasource configuration if the Database is upgraded and you forget to update the JDBC Driver in your modules configuration.
Ref: How to configure a Datasource in WildFly

JNDI NameNotFoundException after Tomcat 8 upgrade

I upgraded from Tomcat 8.0.18 to 8.0.23 and all of the sudden I have a JNDI issue. I looked at the changelogs, Tomcat 8 Changelogs, and I see three JNDI changes, though none strike me as something that would break a previously working configuration.
JNDI related changes were made for bugs 49785, 57587, and an entry under 8.0.19 under "Other".
I am receiving this exception when I start up Tomcat with 8.0.23:
javax.naming.NameNotFoundException: Name [jdbc/MyCluster] is not bound in this Context. Unable to find [jdbc].
In my web application I have a resource link defined:
<Context>
<ResourceLink name="jdbc/MyCluster" global="jdbc/MyCluster" auth="Container" type="javax.sql.DataSource" />
</Context>
I have Tomcat configured with:
<Resource name="jdbc/MyCluster" global="jdbc/MyCluster" ......./>
I am stumped... I cannot figure out what makes my code break after my upgrade from 18 to 23 :(
Just in case anyone was curious about how upgrading from Tomcat 8.0.18 to 8.0.24 could really cause JNDI to screw up, the answer lies in ANT.
ANT Copy documentation
Myself and some other engineers had no idea that ANT Copy does nothing if the file you are trying to overwrite has a newer timestamp... who knew copy had such a complicated condition!?! I believe this is why me and multiple people never looked at the documentation, it is such an unexpected behavior.
Anyways, by upgrading to the newer version of Tomcat my context.xml that contained the resourcelink jdbc/MyCluster was failing to overwrite the newer and more recent timestamp of Tomcat's default context.xml! Once the overwrite flag is set to true, JNDI works again :)

Tomcat and JDBC

I am trying to configure the following on Tomcat.
Resource auth="Container" name="jdbc/yourDataSourceName"
driverClassName="oracle.jdbc.OracleDriver"
factory="oracle.jdbc.pool.OracleDataSourceFactory"
type="oracle.jdbc.pool.OracleDataSource"
connectionCacheProperties="{}"
connectionCachingEnabled="true"
user="foo"
password="bar"
url="jdbc:oracle:thin:#foo.bar.com:1521:foobar"
When I put the following in my app META-INF/context.xml file, I get the following error:
java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.BasicDataSource cannot be cast to oracle.jdbc.pool.OracleDataSource
When I move this to $TOMCAT_HOME/conf/context.xml, it works fine. It is not letting me configure specific to the app. Any ideas?
I have ojdbc6.jar in $TOMCAT_HOME/lib as well as in WEB-INF/lib of my application folder. Please advise. Am I missing something? Thanks for your time.
You can try not to use specific Oracle classes such as "OracleDataSourceFactory" in your datasource configuration. It seems that Oracle Conn.pool is not compatible with DBCP.
Define driverClass only.
You can try something like this:
<Resource
name="jdbc/yourDataSourceName" auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#foo.bar.com:1521:foobar"
user="foo"
password="bar"
maxActive="5" maxIdle="1" maxWait="-1"/>
Hope it will help

Categories

Resources