Camunda use multiple data sources [JBOSS]

Hi,

I wanted to split the ProcessEngine data source and my application datasource (which uses JPA / Hibernate). Therefor I made two entries in the persistence.xml.

<persistence version="2.1"
	xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
        http://xmlns.jcp.org/xml/ns/persistence
        http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
	<persistence-unit name="MyCustom_PU" transaction-type="JTA">
		<!-- If you are running in a production environment, add a managed data 
			source, this example data source is just for development and testing! -->
		<!-- The datasource is deployed as WEB-INF/PCMS-ds.xml, you can find it 
			in the source at src/main/webapp/WEB-INF/PCMS-ds.xml -->
		<jta-data-source>java:/myCustomDb</jta-data-source>
		<exclude-unlisted-classes>false</exclude-unlisted-classes>
		<properties>
			<!-- Properties for Hibernate -->
			<property name="hibernate.hbm2ddl.auto" value="create-drop" />
			<property name="hibernate.show_sql" value="false" />
		</properties>
	</persistence-unit>
	<persistence-unit name="primary">
		<jta-data-source>java:jboss/datasources/ProcessEngine</jta-data-source>
		<properties>
			<!-- Properties for Hibernate -->
			<property name="hibernate.hbm2ddl.auto" value="create-drop" />
			<property name="hibernate.show_sql" value="true" />
		</properties>
	</persistence-unit>
</persistence>

But I get this error: “Persistence unitName was not specified and there are 2 persistence unit definitions in application deployment deployment”

Any hints how to split the data sources?

Thanks in advance.

As Camunda does not use JPA (Hibernate) for persistence, this is not the right place.
You have to do this in your JBoss configuration (standalone.xml).
In the camunda subsystem use
<datasource>java:jboss/datasources/ProcessEngine</datasource>.

2 Likes

I guess that you mean that I should change the Database Server Type from H2 to preferred one. I just did that and changed to MySQL. My question was how to split the process engine database and the application database? I just entered two persistence units in persistence.xml but it didn’t work.

As langfr said, you need to create a second datasource in settings.xml of jboss. (No matter which database type you use …).

There should be already the definition for “java:jboss/datasources/ProcessEngine”. You have to add a second database definition for you own application (e.g. “java:/myCustomDb”).

But consider that you should use xa-datasources when splitting up your database.
See: https://docs.camunda.org/stable/guides/installation-guide/jboss/#bpm-platform-install-the-platform-on-a-vanilla-jboss-using-an-xa-datasource

The persistence.xml looks correct, but without the configuration in standalone.xml this will not work.

2 Likes

If you downloaded the JBoss or Wildfly distributions with predefined Camunda engine you already have 2 datasources in the config file standalone.xml:

            <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 jndi-name="java:jboss/datasources/ProcessEngine" pool-name="ProcessEngine" enabled="true" use-java-context="true" jta="true" use-ccm="true">
                    <connection-url>jdbc:h2:./camunda-h2-dbs/process-engine;DB_CLOSE_DELAY=-1;MVCC=TRUE;DB_CLOSE_ON_EXIT=FALSE</connection-url>
                    <driver>h2</driver>
                    <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
                    <security>
                        <user-name>sa</user-name>
                        <password>sa</password>
                    </security>
                </datasource>
                <drivers>
                    <driver name="h2" module="com.h2database.h2">
                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                    </driver>
                </drivers>
            </datasources>
        </subsystem>

For both datasources you should change the parameters to use another database type for production use, e.g. MySql.
As ExampleDS is a weird name (as it says it’s just an example) you might add a third datasource for your custom DB (java:/myCustomDb). In case you’re thinking about removing ExampleDS or changing the jndi-name of ExampleDS be aware that this is referenced later in standalone.xml. You’ll have to change this reference too.

As Patrick said, you should definitely think about changing those datasources to xa-datasources to be able to have transactions spanning both databases.

And as I already said, there is absolutely no need to change the persistence.xml of your deployment unit.
Camunda does not use JPA entities / Hibernate for persistence.
As you saw, this breaks your application, because the injected EntityManager does not know which persistence-unit to choose.

3 Likes

Ok I got it thank you.

As Bayqush I want to use a other datasourse for storage persistent data for my application.
If in persistence.xml specify two < persistence-unit > I have error "Persistence unitName was not specified and there are 2 persistence unit definitions in application deployment deployment"

Now i specify one < persistence-unit > and my persistence.xml looks this:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
             xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="
        http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

    <persistence-unit name="primary">
        <jta-data-source>java:jboss/datasources/ServiceProvider</jta-data-source>
        <properties>
            <property name="hibernate.hbm2ddl.auto" value="create-drop" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>

</persistence>

my jboss standalone.xml

<subsystem xmlns="urn:jboss:domain:datasources:1.1">
    <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</connection-url>
            <driver>h2</driver>
            <security>
                <user-name>XXX</user-name>
                <password>XXX</password>
            </security>
        </datasource>
        <datasource jta="true" jndi-name="java:jboss/datasources/ProcessEngine" pool-name="ProcessEngine" enabled="true" use-java-context="true" use-ccm="true">
            <connection-url>jdbc:postgresql://localhost:5432/camunda-dbs</connection-url>
            <driver-class>org.postgresql.Driver</driver-class>
            <driver>postgresql</driver>
            <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
            <pool>
                <min-pool-size>2</min-pool-size>
                <max-pool-size>20</max-pool-size>
            </pool>
            <security>
                <user-name>camunda</user-name>
                <password>XXX</password>
            </security>
        </datasource>
        <datasource jta="true" jndi-name="java:jboss/datasources/ServiceProvider" pool-name="ServiceProvider" enabled="true" use-java-context="true" use-ccm="true">
            <connection-url>jdbc:postgresql://localhost:5432/camunda-dbs</connection-url>
            <driver-class>org.postgresql.Driver</driver-class>
            <driver>postgresql</driver>
            <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
            <pool>
                <min-pool-size>2</min-pool-size>
                <max-pool-size>20</max-pool-size>
            </pool>
            <security>
                <user-name>myuser</user-name>
                <password>XXX</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>
        <drivers>
            <driver name="h2" module="com.h2database.h2">
                <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
            </driver>
            <driver name="postgresql" module="org.postgresql">
                <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
            </driver>
        </drivers>
    </datasources>

But I have the folowwing error

16:20:11,897 INFO  [stdout] (http-/127.0.0.1:8080-1) Hibernate: select nextval ('hibernate_sequence')

16:20:11,913 WARN  [com.arjuna.ats.arjuna] (http-/127.0.0.1:8080-1) ARJUNA012140: Adding multiple last resources is disallowed. 
Trying to add LastResourceRecord(XAOnePhaseResource(LocalXAResourceImpl@40ba61a5[connectionListener=284a387c 
connectionManager=c60b8d6 warned=false currentXid=< formatId=131077, gtrid_length=29, bqual_length=36, tx_uid=0:ffff0a100443:-2b8b8312:58b5736a:355a, 
node_name=1, branch_uid=0:ffff0a100443:-2b8b8312:58b5736a:3560, subordinatenodename=null, 
eis_name=java:jboss/datasources/ServiceProvider > productName=PostgreSQL productVersion=9.6.2 jndiName=java:jboss/datasources/ServiceProvider])), 
but already have LastResourceRecord(XAOnePhaseResource(LocalXAResourceImpl@59bfa0ec[connectionListener=756e4af connectionManager=1994aa64 warned=false currentXid=< formatId=131077, gtrid_length=29, bqual_length=36, tx_uid=0:ffff0a100443:-2b8b8312:58b5736a:355a, node_name=1, branch_uid=0:ffff0a100443:-2b8b8312:58b5736a:355c, subordinatenodename=null, 
eis_name=java:jboss/datasources/ProcessEngine > productName=PostgreSQL productVersion=9.6.2 jndiName=java:jboss/datasources/ProcessEngine]))
16:20:11,915 WARN  [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http-/127.0.0.1:8080-1) SQL Error: 0, SQLState: null
16:20:11,915 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http-/127.0.0.1:8080-1) javax.resource.ResourceException: IJ000457: Unchecked throwable in managedConnectionReconnected() cl=org.jboss.jca.core.connectionmanager.listener.TxConnectionListener@284a387c[state=NORMAL managed connection=org.jboss.jca.adapters.jdbc.local.LocalManagedConnection@59fcbb96 connection handles=0 lastUse=1488457211914 trackByTx=false pool=org.jboss.jca.core.connectionmanager.pool.strategy.OnePool@34a6c7a2 pool internal context=SemaphoreArrayListManagedConnectionPool@e631f5c[pool=ServiceProvider] xaResource=LocalXAResourceImpl@40ba61a5[connectionListener=284a387c connectionManager=c60b8d6 warned=false currentXid=null productName=PostgreSQL productVersion=9.6.2 jndiName=java:jboss/datasources/ServiceProvider] txSync=null]
16:20:11,917 ERROR [org.jboss.as.ejb3] (http-/127.0.0.1:8080-1) javax.ejb.EJBTransactionRolledbackException: org.hibernate.exception.GenericJDBCException: Could not open connection
16:20:11,917 ERROR [org.jboss.as.ejb3.invocation] (http-/127.0.0.1:8080-1) JBAS014134: EJB Invocation failed on component RequestBusinessLogic for method public void ru.binbank.bpm.sp.RequestBusinessLogic.persistRequest(org.camunda.bpm.engine.delegate.DelegateExecution): javax.ejb.EJBTransactionRolledbackException: org.hibernate.exception.GenericJDBCException: Could not open connection
	at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleInCallerTx(CMTTxInterceptor.java:138) [jboss-as-ejb3-7.2.0.Final.jar:7.2.0.Final]
	at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:228) [jboss-as-ejb3-7.2.0.Final.jar:7.2.0.Final]
	at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:317) [jboss-as-ejb3-7.2.0.Final.jar:7.2.0.Final]

Is it correct that you want to connect to the same database with both datasources? Just with different users?
(Because it’s just a connection error)

Yes, now is one database, but various schemes
Then, perhaps, there will be different databases.
I do not want to the application tables were in the scheme camunda

I was facing the same issue. I resolved it by using the @PersistenceContext annotation when persisting data with my ejbs.

@PersistenceContext(unitName = “Your persistence unit name”)
image