No externally managed transaction is currently active for this thread - jpa

I have this method which calls package, stored procedures, but it gives me this error:
No externally managed transaction is currently active for this thread.
What should I change or add to fix this?
#Override
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void rebuildIndexes() {
Query query = getEm().createNativeQuery("BEGIN OFPA_ARCHIVING.rebuild_archiving_indexes; END;");
query.executeUpdate();
}

The documentation in https://javaee.github.io/javaee-spec/javadocs/javax/ejb/TransactionAttributeType.html states that
NOT_SUPPORTED
The container invokes an enterprise bean method whose transaction attribute NOT_SUPPORTED with an unspecified transaction context.
You should change the TransactionAttributeType to some value that ensures a transaction. If you are in an EJB class (Stateless, Stateful or Singleton) this is supported by default, so without any annotation you should be good to go.
Which value tonchoose depends on your business case, but tipically you will use:
REQUIRED: This is the default, so.os the same as not using the annotation at all. Usong this means that if the caller of thenmethod doesn't have a transaction a new one will be created.
MANDATORY: The same as before, but if the caller doesn't have a transaction and exception will be thrown (TransactionRequiredException)
or
REQUIRES_NEW: If you want to start and end a transaction with the start and the end of the method.

Related

Persistence of execution information in Axon Saga

We are using the Axon Framework to implement the Saga Pattern in Java. Axon uses two tables (ASSOCIATION_VALUE_ENTRY and SAGA_ENTRY) to store all the necessary information after each step of the saga. And at the end of the process (if it is correct, or, in case of error, all the compensations have been executed), it deletes the registers.
If for any reason, after an error, the compensations cannot be executed, we are able to resume the execution at the point where it failed, based on the stored information. Until here, everything is ok.
The issue came when we wanted to improve the resilience of the process and we checked what happened if the service died during the execution of a saga. According to the above, we expected the information of the execution to be persisted in the tables, but they were empty: the information only appeared when the process couldn't continue due to an error in a compensation (and no final delete action was executed).
Analyzing the source code of the Axon's JpaSagaStore class implementation, the interactions with the database (insert, update and delete) are persisted with a flush instead of a commit. The global commit is managed in the AbstractUnitOfWork class (as far as we understand). And here is where we have the doubts:
According to the literature, the flush writes in the database but the register is in a READ_UNCOMMITED state. The only way to see them in the database would be activating the READ_UNCOMMITED isolation level, with the problematic of the 'dirty reads', right? There would be any additional consideration/issue to have into account?
Does Axon have an alternative in order to ensure the persistence of the saga registers? Mainly if we couldn't activate the READ_UNCOMMITED mode (due to internal policies).
EDIT:
Summarizing it a lot, all starts with this method
public void startSaga(SagaWorkflow sagaWorkflow, Serializable sagaInput) {
StartSagaEvt startSagaEvt = StartSagaEvt.builder().sagaWorkflow(sagaWorkflow).sagaInput(sagaInput).build();
eventBus.publish(GenericEventMessage.asEventMessage(startSagaEvt));
}
Where:
eventBus is the Axon's internal one
sagaInput is simply a Serializable with some input values
SagaWorkflow is a Serializable that models the whole saga flow, whose main attribute is a LinkedList of nodes (the different steps of the saga, each one can have a different logic)
StartSagaEvt is just the POJO that models the event sent to the bus
After this, Axon performs all its 'magic' and finally arrives to the internal code:
AnnotatedSagaRepository.doCreateInstance --> AnnotatedSagaRepository.storeSaga --> [...] --> JpaSagaStore.insertSaga
public void insertSaga(Class<?> sagaType, String sagaIdentifier, Object saga, Set<AssociationValue> associationValues) {
EntityManager entityManager = entityManagerProvider.getEntityManager();
AbstractSagaEntry<?> entry = createSagaEntry(saga, sagaIdentifier, serializer);
entityManager.persist(entry);
for (AssociationValue associationValue : associationValues) {
storeAssociationValue(entityManager, sagaType, sagaIdentifier, associationValue);
}
if (logger.isDebugEnabled()) {
logger.debug("Storing saga id {} as {}", sagaIdentifier, serializedSagaAsString(entry));
}
if (useExplicitFlush) {
entityManager.flush();
}
}
The same applies for the update and delete phases. As far as I know, all the handle of the commit/rollback is performed in the class AbstractUnitOfWork, that intervenes just at the end of the complete saga flow.
This leads me to the following considerations/questions:
what sense has to keep the transaction open during the whole process instead of committing after each step? If for any reason the process fails, goes down, the database is not accessible,... all the saved information is lost.
There must be a design reason for this behavior, but I'm not able to see it. Or maybe there is a configuration to change it (hopefully, although I doubt it).
Thanks in advance for any comment!
EDIT 2
Effectively, we are using it as a kind of state machine, where the saga flow is a sequence of steps, each one with an action and a compensation, and we jump from one to another until reach an "END" status.
#Saga
class GenericSaga {
private EventBus eventBus;
private CustomCommandGateway commandGateway;
[...]
#StartSaga
#SagaEventHandler(associationProperty = "sagaId")
public void startStep(StartSagaEvt startSagaEvt) {
// Initializes de GenericSaga and associate several properties with SagaLifecycle.associateWith(key, value);
[...]
// Transit to the next (first) step
eventBus.publish(GenericEventMessage.asEventMessage(new StepSagaEvt(startSagaEvt)));
}
#SagaEventHandler(associationProperty = "sagaId")
public void nextStep(StepSagaEvt stepSagaEvt) {
// Identifies what is the next step in the defined flow, considering if it should be executed sequentially or concurrently, or if it is the end of the flow and then call the SagaLifecycle.end()
[...]
// Also checks if it has to execute the compensation logic of the step
[...]
// Execute
Serializable actionOutput = commandGateway.sendAndWaitEx(stepAction.getActionInput());
}
#SagaEventHandler(associationProperty = "sagaId")
public void resumeSaga(ResumeSagaEvt resumeSagaEvt) {
// Recover information from the execution that we want to resume
[...]
// Transit to the next step
eventBus.publish(GenericEventMessage.asEventMessage(new StepSagaEvt(resumeSagaEvt)));
}
}
As you can see, we don't have an endSaga annotation, and maybe that's the problem. But in our current situation we have kicked forward, and be have defined our custom implementation of the JpaSagaStore, in order to force a local transaction in the insertSaga and updateSaga methods.
Based on my understanding, I think you are somehow misusing the Saga component from Axon Framework. I assume from your question that you are trying to build a form of a 'state machine' using your own SagaWorkflow object. If that is the case, I have to say this is not how Axon intends the usage of Sagas.
To add to that, let me give you a pseudo-sample of what a Saga should look like.
#Saga
class SagaWorkflow {
private transient CommandGateway commandGateway;
#StartSaga
#SagaEventHandler(associationProperty = "yourProperty")
public void on(SagaInputEvent event) {
// validate, associate with another property and fire a command
SagaLifecycle.associateWith("associationPropertyKey", "associationPropertyValue");
commandGateway.send(new GivenCommand());
}
#SagaEventHandler(associationProperty = "associationPropertyValue")
public void on(AnotherEvent event) {
// validate and fire a command or finish the saga
SagaLifecycle.end();
}
#EndSaga
#SagaEventHandler(associationProperty = "anyProperty")
public void on(FinishSagaEvent event) {
// check if you need to fire extra commands to tell others it's finished or just do it silently
}
}
#Saga Annotation will make sure Axon Framework handles the whole Saga process for you, storing (serializing) it to the database when each (Saga)EventHandler is executed
#SagaEventHandler will make sure the 'Event Handling method' reacts to a given Event, only if it contains the associationProperty as part of the Event (to understand it better, I will share our docs link)
#EndSaga will tell Axon Framework to finalize the Saga after the execution of the method (finalizing means deleting it from the database)
SagaLifecycle provides several 'utilities' methods to interact with the Saga's lifecycle and associations
In the example, I made the CommandGateway transient because the Saga is serialized and stored on the database. You would not Axon to serializer any external component, like the gateway, as well
Of course, there is more to it.
You can check Axon's docs for that. But I hope this gives you enough material and ideas to use Sagas within Axon Framework better!
KR

Can I use SpringData by itself [duplicate]

I'm trying to wire up Spring Data JPA objects manually so that I can generate DAO proxies (aka Repositories) - without using a Spring bean container.
Inevitably, I will be asked why I want to do this: it is because our project is already using Google Guice (and on the UI using Gin with GWT), and we don't want to maintain another IoC container configuration, or pull in all the resulting dependencies. I know we might be able to use Guice's SpringIntegration, but this would be a last resort.
It seems that everything is available to wire the objects up manually, but since it's not well documented, I'm having a difficult time.
According to the Spring Data user's guide, using repository factories standalone is possible. Unfortunately, the example shows RepositoryFactorySupport which is an abstract class. After some searching I managed to find JpaRepositoryFactory
JpaRepositoryFactory actually works fairly well, except it does not automatically create transactions. Transactions must be managed manually, or nothing will get persisted to the database:
entityManager.getTransaction().begin();
repositoryInstance.save(someJpaObject);
entityManager.getTransaction().commit();
The problem turned out to be that #Transactional annotations are not used automatically, and need the help of a TransactionInterceptor
Thankfully, the JpaRepositoryFactory can take a callback to add more AOP advice to the generated Repository proxy before returning:
final JpaTransactionManager xactManager = new JpaTransactionManager(emf);
final JpaRepositoryFactory factory = new JpaRepositoryFactory(emf.createEntityManager());
factory.addRepositoryProxyPostProcessor(new RepositoryProxyPostProcessor() {
#Override
public void postProcess(ProxyFactory factory) {
factory.addAdvice(new TransactionInterceptor(xactManager, new AnnotationTransactionAttributeSource()));
}
});
This is where things are not working out so well. Stepping through the debugger in the code, the TransactionInterceptor is indeed creating a transaction - but on the wrong EntityManager. Spring manages the active EntityManager by looking at the currently executing thread. The TransactionInterceptor does this and sees there is no active EntityManager bound to the thread, and decides to create a new one.
However, this new EntityManager is not the same instance that was created and passed into the JpaRepositoryFactory constructor, which requires an EntityManager. The question is, how do I make the TransactionInterceptor and the JpaRepositoryFactory use the same EntityManager?
Update:
While writing this up, I found out how to solve the problem but it still may not be the ideal solution. I will post this solution as a separate answer. I would be happy to hear any suggestions on a better way to use Spring Data JPA standalone than how I've solve it.
The general principle behind the design of JpaRepositoryFactory and the according Spring integration JpaRepositoryFactory bean is the following:
We're assuming you run your application inside a managed JPA runtime environment, not caring about which one.
That's the reason we rely on injected EntityManager rather than an EntityManagerFactory. By definition the EntityManager is not thread safe. So if dealt with an EntityManagerFactory directly we would have to rewrite all the resource managing code a managed runtime environment (just like Spring or EJB) would provide you.
To integrate with the Spring transaction management we use Spring's SharedEntityManagerCreator that actually does the transaction resource binding magic you've implemented manually. So you probably want to use that one to create EntityManager instances from your EntityManagerFactory. If you want to activate the transactionality at the repository beans directly (so that a call to e.g. repo.save(…) creates a transaction if none is already active) have a look at the TransactionalRepositoryProxyPostProcessor implementation in Spring Data Commons. It actually activates transactions when Spring Data repositories are used directly (e.g. for repo.save(…)) and slightly customizes the transaction configuration lookup to prefer interfaces over implementation classes to allow repository interfaces to override transaction configuration defined in SimpleJpaRepository.
I solved this by manually binding the EntityManager and EntityManagerFactory to the executing thread, before creating repositories with the JpaRepositoryFactory. This is accomplished using the TransactionSynchronizationManager.bindResource method:
emf = Persistence.createEntityManagerFactory("com.foo.model", properties);
em = emf.createEntityManager();
// Create your transaction manager and RespositoryFactory
final JpaTransactionManager xactManager = new JpaTransactionManager(emf);
final JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
// Make sure calls to the repository instance are intercepted for annotated transactions
factory.addRepositoryProxyPostProcessor(new RepositoryProxyPostProcessor() {
#Override
public void postProcess(ProxyFactory factory) {
factory.addAdvice(new TransactionInterceptor(xactManager, new MatchAlwaysTransactionAttributeSource()));
}
});
// Create your repository proxy instance
FooRepository repository = factory.getRepository(FooRepository.class);
// Bind the same EntityManger used to create the Repository to the thread
TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em));
try{
repository.save(someInstance); // Done in a transaction using 1 EntityManger
} finally {
// Make sure to unbind when done with the repository instance
TransactionSynchronizationManager.unbindResource(getEntityManagerFactory());
}
There must be be a better way though. It seems strange that the RepositoryFactory was designed to use EnitiyManager instead of an EntityManagerFactory. I would expect, that it would first look to see if an EntityManger is bound to the thread and then either create a new one and bind it, or use an existing one.
Basically, I would want to inject the repository proxies, and expect on every call they internally create a new EntityManager, so that calls are thread safe.

TransactionTimeout annotation seems not to override global seetting on JBoss 5.x

I have an EJB 3.0 based applicattion deployed on JBoss 5.1. The global value for transaction timeout configured at ${JBOSS_HOME}/server/default/deploy/transaction-jboss-beans.xml on property transactionTimeout is fine for most of our EJB methods. However, we have some methods whose duration is expected to be much longer than the value set there. We'd like to override the timeout specifically for those methods.
We've tried to do it as explained here, i.e. let the global value with a sensible value and then try to override specifically some methods via deployment descriptor at jboss.xml or via jboss specific annotations within the method.
The methods are within stateless session beans container managed. I've even forced those methods to create a new transaction as in some places is said that the annotation only works if the transaction is created in that moment.
../..
import org.jboss.ejb3.annotation.TransactionTimeout;
../..
#Override
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
#TransactionTimeout(900)
public FileInfoObject setFileVariable(Desk desk, String variable, int maxBytes,
String mimeAccepted, FileWithStream file)
throws ParticipationFinishedException, PersistenceException {
../..
}
The expected behavior is that for this method the timeout should be 900.
The actual behavior is quite fine and is the following:
if global timeout > method timeout then method timeout is applied
if global timeout <= method timeout then global timeout is applied
It seems that the applied timeout is the minimum of both which is a real problem if what we want is to extend the timeout for a specific method overriding the global value.
Any ideas? Am I missing something?

Best way to handle constraint violations when using EJB 3.0 and CMP

I have a web service (built using jaxb/jaxws) that invokes a stateless EJB to store some data in the database. The data is being stored as an entity bean. The entity bean has a unique constraint applied to it via the #Column(unique = true) annotation.
When the web service attempts to save data, the transaction fails, and rightfully so. The problem is that since I am using CMP, the transaction is not committed until after the call to the stateless EJB. The end result is that I am not able to trap the exception and it is getting funneled up to the WS stack and results in an ambiguous fault containing the string: Error committing transaction:;nested exception is: weblogic.transaction.internal.AppSetRollbackOnlyException.
Is there a way to catch the exception being thrown so I can provide more information to the caller? Thank you.
Version information:
Application Server: Oracle Weblogic 10.3
Persistence Provider: Hibernate 3.2.5.ga (JPA 1.0)
JDK/JRE: 1.6_0_05 (provided by Weblogic install)
Update:
I tried to implement an EJB 3 interceptor around the method invocation and this does not appear to work.
public class TestInterceptor {
#AroundInvoke
public Object logCall(InvocationContext context) throws Exception {
System.out.println("Invoking method: " + context.getMethod().getName());
try {
return context.proceed();
} catch (Throwable t) {
System.out.println("I caught an exception: " + t.getMessage());
throw new Exception(t);
}
}
The reason I think this doesn't work is because the processing chain is such that the actual persist happens outside of the method (of course).
You could try using Bean Validation. It's nicely connected with the JPA (invoked during pre-persist, pre-update and pre-remove phases and can be used in different layers of your application.
Unfortunately, as far as I know, if a validation constraint violation occurs, the transaction is marked for rollback... I don't know how you could cope with that but one (seems nasty and untested) way I could think of is to inject a ValidatorFactory and validate the object by yourself. Perhaps then you could catch the ValidationException.
EDIT: I'm not sure if the Bean Validation was available in Java EE 5.
EDIT 2: You can create an interceptor which will catch the exception thrown by the JPA (or more precisely by the database). As the interceptor is invoked as a part of the same transaction as the EJB method you might need to explicitly invoke EntityManager#flush(-) to synchronise changes with the database.

REQUIRES_NEW annotated method is executed without a transaction?

I have a stateless bean resposible for persisting entities to a database. This stateless bean is called by a message bean's onMessage method. The wired thing is that on the first message everything works fine, but on the next message the method responsible for persisting is invoked outside a transaction, even though the method is annotated with REQUIRES_NEW.
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public StateChange persistChange(long deviceId, ...) {
...
StateChange change = new StateChange(...);
em.persist(change);
em.refresh(change); // To provoke the error
return change;
}
Calling refresh triggers the following exception:
Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
Any ideas? I'm fairly new to JTA so I might have missed something important?
I tried a lot to solve it and after about 16 hours or so it seems to be working. I'm not sure exactly what did the trick, but it might be the upgrade to Glassfish 2.1.
Finally able to sleep at night again!