Skip to content
Snippets Groups Projects
Commit 0ccc9a4f authored by Maciej Swiderski's avatar Maciej Swiderski
Browse files

BZ833609 - JPAKnowledgeService sessions fail on CMT under other App Servers

(cherry picked from commit e8ea6c5c)
parent f5d74236
Branches
Tags
No related merge requests found
......@@ -634,6 +634,51 @@ ut.commit();</programlisting>
value="org.hibernate.transaction.JBossTransactionManagerLookup" /&gt;
</programlisting>
<section>
<title>Container managed transaction</title>
<para>Special consideration need to be taken when embedding jBPM inside an application that
exucutes in Container Managed Tansaction (CMT) mode, for instance EJB beans. This especially
applies to application servers that does not allow accessing UserTransaction instance from
JNDI when being part of container managed transation, e.g. WebSphere Application Server.
Since default implementation of transaction manager in jBPM is based on UserTransaction
to get transaction status which is used to decide if transaction should be started or not,
in environments that prevent accessing UserTrancation it won't do its job.
To secure proper execution in CMT environments a dedicated transaction manager implementation
is provided:</para>
<programlisting>org.jbpm.persistence.jta.ContainerManagedTransactionManager</programlisting>
<para>This transaction manager expects that transaction is active and thus will always
return ACTIVE when invoking getStatus method. Operations like begin, commit, rollback
are no-op methods as transaction manager runs under managed transaction and can't affect it.
</para>
<note>
<para>To make sure that container is aware of any exceptions that happened during
process instance execution, user needs to ensure that exceptions thrown by the
engine are propagated up to the container to properly rollback transaction.</para>
</note>
<para>To configure this transaction manager following must be done:</para>
<itemizedlist>
<listitem>Insert transaction manager and peristence context manager into environment prior
to creating/loading session
<programlisting>
Environment env = EnvironmentFactory.newEnvironment();
env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
env.set(EnvironmentName.TRANSACTION_MANAGER, new ContainerManagedTransactionManager());
env.set(EnvironmentName.PERSISTENCE_CONTEXT_MANAGER, new JpaProcessPersistenceContextManager(env));
</programlisting>
</listitem>
<listitem>configure JPA provider (example hibernate and WebSphere)
<programlisting>
&lt;property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/&gt;
&lt;property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup"/&gt;
</programlisting>
</listitem>
</itemizedlist>
<para>With following configuration jBPM should run properly in CMT environment.</para>
</section>
</section>
<section>
......
/*
* Copyright 2012 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jbpm.persistence.jta;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.transaction.TransactionSynchronizationRegistry;
import org.drools.persistence.TransactionManager;
import org.drools.persistence.TransactionSynchronization;
import org.drools.persistence.TransactionSynchronizationRegistryHelper;
import org.drools.persistence.jta.JtaTransactionManager;
/**
* Dedicated implementation of <code>TransactionManager</code> that should be used when:
* <ul>
* <li>jBPM engine is embedded in Container Managed Transaction (CMT) environment like EJB container</li>
* <li>container that does not allow accessing UserTransaction (when running in CMT mode)
* - e.g. WebSphere Appliation Server</li>
* </ul>
* Instance of this transaction manager must be set on Environment together with
* Persistence context manager instance to take effect.
* <code>
* Environment env = EnvironmentFactory.newEnvironment();
* env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
* env.set(EnvironmentName.TRANSACTION_MANAGER, new ContainerManagedTransactionManager());
* env.set(EnvironmentName.PERSISTENCE_CONTEXT_MANAGER, new JpaProcessPersistenceContextManager(env));
* </code>
* Since it dedicated to be run in CMT begine/commit/rollback are no-op methods. <br/>
* Status of the transaction is always Active.
*/
public class ContainerManagedTransactionManager implements TransactionManager {
protected TransactionSynchronizationRegistry txSyncRegistry;
public ContainerManagedTransactionManager() {
this.txSyncRegistry = (TransactionSynchronizationRegistry) findTransactionSynchronizationRegistry();
}
public boolean begin() {
// do nothing
return false;
}
public void commit(boolean arg0) {
// do nothing
}
public int getStatus() {
return TransactionManager.STATUS_ACTIVE;
}
public void registerTransactionSynchronization(TransactionSynchronization arg0) {
if (txSyncRegistry != null) {
TransactionSynchronizationRegistryHelper.registerTransactionSynchronization( txSyncRegistry, arg0 );
}
}
public void rollback(boolean arg0) {
// do nothing
}
protected Object findTransactionSynchronizationRegistry() {
String jndiName = JtaTransactionManager.DEFAULT_TRANSACTION_SYNCHRONIZATION_REGISTRY_NAME;
try {
InitialContext context = new InitialContext();
Object tsrObject = context.lookup(jndiName);
return tsrObject;
} catch (NamingException ex) {
}
return null;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment