Using multiple datasources with Wildfly - java

I am using multiple datasources in my java web-application.
Here is Wildfly configuration (standalone mode):
<datasource jta="false" jndi-name="java:jboss/datasources/DS1" pool-name="DS1" enabled="true" use-ccm="false">
<connection-url>URL1</connection-url>
<driver>ojdbc7</driver>
<security>
<user-name>login</user-name>
<password>password</password>
</security>
<validation>
<validate-on-match>false</validate-on-match>
<background-validation>false</background-validation>
</validation>
<statement>
<share-prepared-statements>false</share-prepared-statements>
</statement>
</datasource>
<datasource jta="false" jndi-name="java:jboss/datasources/DS2" pool-name="DS2" enabled="true" use-ccm="false">
<connection-url>URL2</connection-url>
<driver-class>org.h2.Driver</driver-class>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
<validation>
<validate-on-match>false</validate-on-match>
<background-validation>false</background-validation>
</validation>
<statement>
<share-prepared-statements>false</share-prepared-statements>
</statement>
Jboss.xml in my ejb subproject:
<session>
<ejb-name>Bean1</ejb-name>
<resource-description>
<res-ref-name>DS1</res-ref-name>
<jndi-name>java:jboss/datasources/DS1</jndi-name>
</resource-description>
</session>
<session>
<ejb-name>Bean2</ejb-name>
<resource-description>
<res-ref-name>DS2</res-ref-name>
<jndi-name>java:jboss/datasources/DS2</jndi-name>
</resource-description>
</session>
In EJB Bean1/Bean2 datasources are called via
#Resource(name="DS1/DS2")
private DataSource dataSource;
....
Connection connection = dataSource.getConnection();
Using shown configuration I have faced following problems :
I can access datasource only if it is set as a default in <default-bindings> section of my standalone-full.xml. If it is empty, I get
"JBAS014771: Services with missing/unavailable dependencies"
pointing to the list of datasources used in beans during deployment.
If I set DS1 as a default one, next time DS2 is injected, it will contain
LocalManagedConnectionFactory
pointing to DS1 in dataSource.mcf variable
As I've understood from this topic
Why different persistence units with separated data sources query the same data source?
this problem may be caused by container-managed persistance.
But in given case I am not using any ORM. So I am only able to manipulate datasources using jndi and server configuration.
So is there any way I can resolve this situation by using some additional wildfly configuration / any manipulations with application or I have to use ORM and manage persistance by myself ?
Thanks for replies.

it's recommended to use an ORM (JPA in best case), so you will use entityManager and persitence.xml for using multiple data sources.
<persistence-unit name="DB1_PU">
<jta-data-source>java:jboss/datasources/ds1</jta-data-source>
</persistence-unit>
<persistence-unit name="DB2_PU">
<jta-data-source>java:jboss/datasources/ds2</jta-data-source>
</persistence-unit>
and you can call the DS like :
#PersistenceContext(unitName = "DB1_PU")
protected EntityManager entityManager1;
#PersistenceContext(unitName = "DB2_PU")
protected EntityManager entityManager2;

Related

com.sybase.jdbc4.jdbc.SybConnection#36d4f39c: com.sybase.jdbc4.jdbc.SybSQLException: dual not found

I have upgraded sybase data base driver from jconn3.jar to jconn4.jar in my project. I get the below error when my application connects to Sybase data source. I have deployed my application on JBOSS 7 server.
[org.jboss.jca.adapters.jdbc.local.LocalManagedConnectionFactory] (default task-48) IJ030027: Destroying connection that is not valid, due to the following exception: com.sybase.jdbc4.jdbc.SybConnection#36d4f39c: com.sybase.jdbc4.jdbc.SybSQLException: dual not found. Specify owner.objectname or use sp_help to check whether the object exists (sp_help may produce lots of output).
at com.sybase.jdbc4.tds.Tds.processEed(Tds.java:4131)
at com.sybase.jdbc4.tds.Tds.nextResult(Tds.java:3247)
at com.sybase.jdbc4.jdbc.ResultGetter.nextResult(ResultGetter.java:78)
at com.sybase.jdbc4.jdbc.SybStatement.nextResult(SybStatement.java:294)
at com.sybase.jdbc4.jdbc.SybStatement.nextResult(SybStatement.java:276)
at com.sybase.jdbc4.jdbc.SybStatement.executeLoop(SybStatement.java:2828)
at com.sybase.jdbc4.jdbc.SybStatement.execute(SybStatement.java:2815)
at com.sybase.jdbc4.jdbc.SybStatement.execute(SybStatement.java:1447)
at org.jboss.jca.adapters.jdbc.CheckValidConnectionSQL.isValidConnection(CheckValidConnectionSQL.java:74)
at org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnectionFactory.isValidConnection(BaseWrapperManagedConnectionFactory.java:1272)
at org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnectionFactory.getInvalidConnections(BaseWrapperManagedConnectionFactory.java:1085)
What does 'dual not found' in the error mean?
Can you please let me know what is the root cause of this issue and help to resolve it?
My data source configuration is shown below :
<datasource jta="false" jndi-name="java:/SybaseDS" pool-name="SybaseDS" enabled="true" use-ccm="false">
<connection-url>*********************</connection-url>
<driver-class>com.sybase.jdbc4.jdbc.SybDriver</driver-class>
<driver>sybase</driver>
<pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>100</max-pool-size>
</pool>
<validation>
<check-valid-connection-sql>select 1 from dual</check-valid-connection-sql>
<validate-on-match>false</validate-on-match>
<background-validation>false</background-validation>
<exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.sybase.SybaseExceptionSorter"/>
</validation>
<timeout>
<set-tx-query-timeout>false</set-tx-query-timeout>
<blocking-timeout-millis>0</blocking-timeout-millis>
<idle-timeout-minutes>15</idle-timeout-minutes>
<use-try-lock>0</use-try-lock>
<allocation-retry>0</allocation-retry>
<allocation-retry-wait-millis>0</allocation-retry-wait-millis>
</timeout>
<statement>
<share-prepared-statements>false</share-prepared-statements>
</statement>
</datasource>
I will resolved this issue by removing the connection validation query in the data source as shown below :
<check-valid-connection-sql>select 1 from dual</check-valid-connection-sql>
The dual table doesn't exist in Sybase database.

Monitoring datasource connection pool on Wildfly9

I'm working on the project where I'm trying to get the runtime statistics of my datasource connection pool which I placed into /deployment folder using Wildfly-9.
I searched for it and I found the configuration file which exist inside /standalone folder named as standalone.xml file giving me the statistics of datasource connection poool by using below code :
<datasource jta="true" jndi-name="java:jboss/datasources/DemoDS" pool-name="DemoDS" enabled="true" use-ccm="true" statistics-enabled="true">
<connection-url>jdbc:mysql://localhost:3306/demo?zeroDateTimeBehavior=convertToNull</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<driver>mysql</driver>
<pool>
<min-pool-size>1</min-pool-size>
<max-pool-size>50</max-pool-size>
</pool>
<security>
<user-name>root</user-name>
<password>root</password>
</security>
<validation>
<valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker"/>
<background-validation>true</background-validation>
<exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter"/>
</validation>
</datasource>
Hit this url I got this:
http://localhost:9990/management/subsystem/datasources/data-source/DemoDS/statistics/pool?include-runtime=true
I get the following json string:
You get the following json string:
{
"ActiveCount":4,
"AvailableCount":48,
"AverageBlockingTime":0,
"AverageCreationTime":21,
"AverageGetTime":17,
"AveragePoolTime":195196,
"AverageUsageTime":43,
"BlockingFailureCount":0,
"CreatedCount":4,
"DestroyedCount":0,
"IdleCount":2,
"InUseCount":2,
"MaxCreationTime":47,
"MaxGetTime":47,
"MaxPoolTime":386185,
"MaxUsageTime":134,
"MaxUsedCount":4,
"MaxWaitCount":0,
"MaxWaitTime":0,
"TimedOut":0,
"TotalBlockingTime":0,
"TotalCreationTime":87,
"TotalGetTime":88,
"TotalPoolTime":780787,
"TotalUsageTime":217,
"WaitCount":0,
"XACommitAverageTime":0,
"XACommitCount":0,
"XACommitMaxTime":0,
"XACommitTotalTime":0,
"XAEndAverageTime":0,
"XAEndCount":0,
"XAEndMaxTime":0,
"XAEndTotalTime":0,
"XAForgetAverageTime":0,
"XAForgetCount":0,
"XAForgetMaxTime":0,
"XAForgetTotalTime":0,
"XAPrepareAverageTime":0,
"XAPrepareCount":0,
"XAPrepareMaxTime":0,
"XAPrepareTotalTime":0,
"XARecoverAverageTime":0,
"XARecoverCount":0,
"XARecoverMaxTime":0,
"XARecoverTotalTime":0,
"XARollbackAverageTime":0,
"XARollbackCount":0,
"XARollbackMaxTime":0,
"XARollbackTotalTime":0,
"XAStartAverageTime":0,
"XAStartCount":0,
"XAStartMaxTime":0,
"XAStartTotalTime":0,
"statistics-enabled":true
}
Since I have many datasource file I cannot place into individual standalone.xml file.
So anyone knows how I will get the runtime statistics of my datasource connection pool which I placed into /deployment folder?
From Wildfly CLI:
Check if stats enabled for datasource
/subsystem=datasources/data-source=(your datasourcename):read-attribute(name=statistics-enabled)
Enable stats: requires restart of Wildfly service afterwards
/subsystem=datasources/data-source=(your datasource):write-attribute(name=statistics-enabled, value=true)
After restart start CLI and run the check command again.

Openshift doesn't deploy persistence.xml?

Hello there internet community,
So I went into JAVA and started test things localy on my WildFly 8. Everything is OK with maven web projects, looks and works good. Now I decided to go to openshift as the first choice of free cloud for JAVA. I managed to do all needed to get my eclipse and enviorment to work/upload/update server. Then I decided to add MySQL with JPA/Hibernate and localy everything is OK. BUT, when I upload to openshift I get the following error:
2015-05-30 06:18:13,289 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-2) MSC000001: Failed to start service jboss.deployment.unit."ROOT.war".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."ROOT.war".WeldStartService: Failed to start service
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_45]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_45]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_45]
Caused by: java.lang.IllegalArgumentException: JBAS016069: Error injecting persistence unit into CDI managed bean. Can't find a persistence unit named in deployment ROOT.war
at org.jboss.as.weld.services.bootstrap.WeldJpaInjectionServices.getScopedPUName(WeldJpaInjectionServices.java:110)
at org.jboss.as.weld.services.bootstrap.WeldJpaInjectionServices.registerPersistenceContextInjectionPoint(WeldJpaInjectionServices.java:73)
at org.jboss.weld.injection.ResourceInjectionFactory$PersistenceContextResourceInjectionProcessor.getResourceReferenceFactory(ResourceInjectionFactory.java:313)
at org.jboss.weld.injection.ResourceInjectionFactory$PersistenceContextResourceInjectionProcessor.getResourceReferenceFactory(ResourceInjectionFactory.java:301)
at org.jboss.weld.injection.ResourceInjectionFactory$ResourceInjectionProcessor.createFieldResourceInjection(ResourceInjectionFactory.java:207)
at org.jboss.weld.injection.ResourceInjectionFactory$ResourceInjectionProcessor.createResourceInjections(ResourceInjectionFactory.java:182)
at org.jboss.weld.injection.ResourceInjectionFactory.discoverType(ResourceInjectionFactory.java:405)
at org.jboss.weld.injection.ResourceInjectionFactory.getResourceInjections(ResourceInjectionFactory.java:92)
at org.jboss.weld.injection.producer.ResourceInjector.(ResourceInjector.java:59)
at org.jboss.weld.injection.producer.ResourceInjector.of(ResourceInjector.java:49)
at org.jboss.weld.injection.producer.BeanInjectionTarget.(BeanInjectionTarget.java:62)
at org.jboss.weld.injection.producer.BeanInjectionTarget.createDefault(BeanInjectionTarget.java:46)
at org.jboss.weld.manager.InjectionTargetFactoryImpl.chooseInjectionTarget(InjectionTargetFactoryImpl.java:128)
at org.jboss.weld.manager.InjectionTargetFactoryImpl.createInjectionTarget(InjectionTargetFactoryImpl.java:87)
at org.jboss.weld.bean.ManagedBean.(ManagedBean.java:91)
at org.jboss.weld.bean.ManagedBean.of(ManagedBean.java:71)
at org.jboss.weld.bootstrap.AbstractBeanDeployer.createManagedBean(AbstractBeanDeployer.java:264)
at org.jboss.weld.bootstrap.BeanDeployer.createClassBean(BeanDeployer.java:228)
at org.jboss.weld.bootstrap.ConcurrentBeanDeployer$2.doWork(ConcurrentBeanDeployer.java:78)
at org.jboss.weld.bootstrap.ConcurrentBeanDeployer$2.doWork(ConcurrentBeanDeployer.java:75)
at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:60)
at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:53)
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [rt.jar:1.8.0_45]
... 3 more
as you can see the error comes from
JBAS016069: Error injecting persistence unit into CDI managed bean. Can't find a persistence unit named in deployment ROOT.war
here is my PersistenceContext injection point:
<pre><code>
#SessionScoped
public class IndexWebBean implements Serializable {
private static final long serialVersionUID = 1L;
#PersistenceContext
EntityManager em;
#Inject
SettingsBean settingsBean;
private boolean isUserAdmin = true;
private String selectedTheme = "aristo";
private String aboutMessage;
private NotificationController notificationController;
public IndexWebBean() {}
#PostConstruct
public void Init() {}
}
</code></pre>
here is persistence.xml:
<pre><code>
<persistence-unit name="ROOT">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/MySQLDS</jta-data-source>
<class>ROOT.ROOT.entity.User</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.connection.useUnicode" value="true" />
<property name="hibernate.connection.characterEncoding" value="UTF-8" />
</properties>
</persistence-unit>
</code></pre>
standalone.xml:
<pre><code>
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<datasource jta="true" jndi-name="java:jboss/datasources/MySQLDS" pool-name="MySQL" enabled="true" use-ccm="true">
<connection-url>jdbc:mysql://localhost:3306/crafty</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<driver>com.mysql</driver>
<security>
<user-name>XX</user-name>
<password>XX</password>
</security>
<validation>
<validate-on-match>false</validate-on-match>
<background-validation>false</background-validation>
</validation>
<timeout>
<set-tx-query-timeout>false</set-tx-query-timeout>
<blocking-timeout-millis>0</blocking-timeout-millis>
<idle-timeout-minutes>0</idle-timeout-minutes>
<query-timeout>0</query-timeout>
<use-try-lock>0</use-try-lock>
<allocation-retry>0</allocation-retry>
<allocation-retry-wait-millis>0</allocation-retry-wait-millis>
</timeout>
<statement>
<share-prepared-statements>false</share-prepared-statements>
</statement>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
<driver name="com.mysql" module="com.mysql"/>
</drivers>
</datasources>
</code></pre>
(alot of text has been outputed, so quick reminder: localy eveyrthing works like a charm)
So I went with "rhc ssh -a appname" and checked that in wildfly/standalone/deployments/ROOT.war IS compiled in standalone WAR file, while in local system the whole project is folder based - it's not compiled to WAR. That's NOT especialy a bad thing, but the point is that when I unziped the WAR, I checked if folder structure is the same as local folder structure. It seems that it's NOT. There is not META-INF in ROOT.war/WEB-INF/classes where persistence.xml actually stands ... that was a strange one! What I did is to add #PersistenceContext(unitName="ROOT") to em injection point, manualy create that folder (META-INF), manualy upload my persistence.xml from local computer, and rename ROOT.war.failed to ROOT.war.dodeply to re-deploy, and it worked. But then I made some changes to the code localy, again it worked like a charm, published to openshift thru eclipse and still openshift complied my ROOT.war to webarch and META-INF and standalone.xml are nowhere to be found which yet leaded to the same error. So my question is: what am I doing wrong if everything works great localy, and doesn't when is uploaded to openshift? Thanks in advance for your time.
PS.: English is not my native sorry for any errors. I hope everything is readable and understandable. Any more additional info I will provide on demand.

How to configure JNDI datasource in Jboss using HikariCP?

How to configure a JNDI datasource in jboss configuration file using HikariCP I can't find aything in the help contents of Hikari there is only Tomcat configuration .
I have a Spring webb app, I have a datasource defined inside the application and I want to move this to a JNDI datasource.
My datasource definition is:
<datasource jndi-name="java:jboss/datasources/mydatasource" pool-name="mydatasource" enabled="true" use-java-context="true">
<connection-url>jdbc:postgresql://localhost:5432/database</connection-url>
<driver-class>org.postgresql.Driver</driver-class>
<datasource-class>com.zaxxer.hikari.HikariDataSource</datasource-class>
<driver>postgresql</driver>
<pool>
<min-pool-size>5</min-pool-size>
<max-pool-size>10</max-pool-size>
</pool>
<security>
<user-name>user</user-name>
<password>password</password>
</security>
</datasource>
And the driver definition:
<driver name="postgresql" module="org.postgresql.jdbc">
<xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
</driver>
I'm getting this error among others:
ERROR [org.jboss.as.controller.management-operation] (Controller Boot Thread) JBAS014613: Operation ("add") failed - address: ([
("subsystem" => "datasources"),
("data-source" => "mydatasource")
]) - failure description: {"JBAS014771: Services with missing/unavailable dependencies" => [
"jboss.driver-demander.java:jboss/datasources/mydatasource is missing [jboss.jdbc-driver.postgresql]",
"jboss.data-source.java:jboss/datasources/mydatasource is missing [jboss.jdbc-driver.postgresql]"
]}
So what is the right way to configure this?
EDIT:
Following the guide to create the Tomcat resource and using the information provided in this question I have come to this DataSource definition:
<datasource jta="false" jndi-name="java:jboss/mydatasource" pool-name="mydatasource" enabled="true" use-ccm="false">
<connection-url>jdbc:postgresql://localhost:5432/databasename</connection-url>
<driver-class>org.postgresql.Driver</driver-class>
<driver>postgresql</driver>
<pool>
<min-pool-size>5</min-pool-size>
<max-pool-size>10</max-pool-size>
<flush-strategy>FailingConnectionOnly</flush-strategy>
</pool>
<security>
<user-name>username</user-name>
<password>password</password>
</security>
<validation>
<validate-on-match>false</validate-on-match>
<background-validation>false</background-validation>
</validation>
<statement>
<share-prepared-statements>false</share-prepared-statements>
</statement>
</datasource>
I installed the postgresql driver in Jboss and declared it.
And in Spring configuration
...
#Bean
public DataSource dataSource() {
final JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
dataSourceLookup.setResourceRef(true);
DataSource dataSourceTemp = null;
try {
dataSourceTemp = dataSourceLookup.getDataSource("jdbc/mydatasource");
} catch (DataSourceLookupFailureException e) {
log.error("DataSource not found.");
}
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDataSource(dataSourceTemp);
return new HikariDataSource(hikariConfig);
}
...
This code based on HikariJNDIFactory code,everything seems to work but I think I have to create a properties object with the properties of the connection what properties I have to include in the object?
Here is the configuration for a "pure" Tomcat JNDI DataSource:
https://github.com/brettwooldridge/HikariCP/wiki/JNDI-DataSource-Factory-(Tomcat,-etc.)
You might also find this answer Re: Spring + Tomcat + JNDI informative:
How to use JNDI DataSource provided by Tomcat in Spring?
Also recommended is the latest HikariCP 2.0.1.

JBoss AS 7 Datasource Configuration - Transaction not active

I have this datasource configuration on my JBOSS AS 7 in standalone.xml:
<subsystem xmlns="urn:jboss:domain:datasources:1.0">
<datasources>
<datasource jndi-name="java:jboss/MyJndiDS" pool-name="MyPoolDS" enabled="true" jta="true" use-java-context="false" use-ccm="true">
<connection-url>
jdbc:postgresql://192.168.2.125:5432/t_report
</connection-url>
<driver>
org.postgresql
</driver>
<transaction-isolation>
TRANSACTION_READ_COMMITTED
</transaction-isolation>
<pool>
<min-pool-size>
3
</min-pool-size>
<max-pool-size>
7
</max-pool-size>
<prefill>
true
</prefill>
<use-strict-min>
false
</use-strict-min>
<flush-strategy>
FailingConnectionOnly
</flush-strategy>
</pool>
<security>
<user-name>
my_user
</user-name>
<password>
my_pass
</password>
</security>
<statement>
<prepared-statement-cache-size>
32
</prepared-statement-cache-size>
</statement>
</datasource>
...
...
</datasources>
</subsystem>
And when I login and logout 7 times with one and the same user the next time i try to login I get Transaction not active error. How can I fix this? I don't want to increase the max-pool-size. Here is my logout method:
import javax.faces.context.ExternalContext;
#Inject ExternalContext ec;
public void validateUserLogOut() {
HttpServletRequest request = (HttpServletRequest)ec.getRequest();
request.getSession().invalidate();
this.setUserLoggedIn(false);
navigation.logout();
}
I think your issue is less the datasource (this only exposes it), but rather the fact that the login module seems to keep connections open and is not returning them into the pool.
Due to request of user503413 I will admit the mistake I've made with a disgrace: I have forgotten to close the connection after using it (connection.close()). If you don't close your connection it will not return it to the pool and since you've limited and reached the max-pool-size (7 in my case) no new connection is going to be created. So the lesson here is always be sure to close your connections. Also close your prepared statements or else you'll get a memory leak.

Categories

Resources