I know that having transaction attribute on a static method inside an EJB is incorrect. There won't be any exception thrown but the transaction attribute will not have any effect.
However, if an EJB has a method callMe() with a transaction attribute (let's say REQUIRED) and this method invokes a static method that is within the same EJB or another helper class, will the static method be part of the container transaction?
Yes, it will be inside the transaction. The transaction is open for that entire method and anything called inside of it will execute inside the transaction unless you use special transaction attribute methods like : NOT_SUPPORTED or REQUIRES_NEW obviously.
When one talks about EJBs, one talk about beans' instances and not about the class itself.
Furthermore, in an enterprise bean with container-managed transaction demarcation, the EJB container sets the boundaries of the transactions associated to the bean instance, either session or message-driven.
Finally, as the EJB 3.2 spec states, since the transaction attributes for the methods of a bean class may be specified on the class, the business
methods of the class, or both, and these methods can't be static, any static methods declared on the bean will not take part on the container-managed transactions.
As a side note, on the Revision History section of the EJB 3.2 specification (part A.8 Final Release Candidate), is mentioned the following:
Clarified that no-interface view and no-methods interface message listener methods are non-static public methods
Related
I have an Ingestion class that exposes a single method ingest. This method processes each section of a passed in form (section 1, section 2, etc, etc).
I have private methods for each section, saving the entity as it processes through. I'm aware that #Transactional has no effect on private methods, however I do not want to expose these methods but would like to use the functionality that #Transactional provides.
I'm looking to make sure each section completes in its own Transaction; I could do this through 'AspectJ' (as other SO answers have suggested) instead of Spring's out the box implementation, but I am trying to avoid due to the system wide changes it would cause.
Any thoughts on another approach?
The pseudo code provided below gives a general idea on the structure of the class:
public Class Ingestion {
// Autowired Repo's
...
...
#Transactional
public void ingest(Form form){
this.processSection1(form);
this.processSection2(form);
this.processSection3(form);
}
#Transactional
private void processSection1(Form form){
// do specific section 1 logic
section1Repo.save(form);
}
#Transactional
private void processSection2(Form form){
// do specific section2 logic
section2Repo.save(form);
}
#Transactional
private void processSection3(Form form){
// do specific section3 logic
section3Repo.save(form);
}
}
=========================================================================
This is not a duplicate question as marked in the comments. I know #Transactional doesnt work on private methods. My question is more along the lines of 'how do we get around this Spring AOP issue without having to use AspectJ'
The reason this doesn't work is that annotations like #Transactional add additional functionality that is intercepted by Spring's proxy object that wraps the actual object. But when you call a private method on an object with the this keyword, you're going straight to the real object and bypassing the proxy.
One way to solve this is to #Autowire the object into itself, and make the transactional calls via that autowired variable. You can still access private methods that way, and the call will be to a Spring-managed proxy instead of the bare object.
You may extract these three processing methods in another class, make them public, but set the class constructor access level to package-local (but not private, since Spring can't proxy classes with private constructors), so no classes from other packages could access these methods just because they are not able to instantiate their class. It doesn't hide these methods completely, but may fit your needs. This trick can be done with an inner class as well (note that it must be declared with package-local access).
To completely hide these methods, you may make use of declarative transaction management by injecting TransactionTemplate bean and using its execute method in private methods. This feature comes out-of-the-box. See more here.
Also, take note that for creating new transaction on executing method B from method A, method B must be declared #Transactional with propagation type REQUIRES_NEW. Otherwise, any nested methods will be invoked in the same transaction started by initial calling method.
What happens when I call one transactional method from another transactional method, now my second transactional method completed, and it came back in 1st transactional method, and unfortunately it fail, so will it roll back everything, means will it roll back 2nd transactional method changes..?? Note: both method are in same class
#Transactional
public void method1(){
//do something
call method2();
//do something
...
...
failed here
}
#Transactional
public void method2(){
//do something
save()
}
So in above example will it rollback whatever I saved in 2nd transactional method?
It depends on the txType. By default it is REQUIRED. So the first method starts the transaction and the same transaction is used for the call to method2.
Also be careful that a method call inside the same object does not trigger the transaction processing. As typically the transaction handling is handled as proxy that only works when calling an injected other bean. In your example you would not notice a difference though.
A case where this would matter is if method1 is not #Transactional and method2 is. In this case there would be no transaction at all.
If both methods are in the same class, the #Transactional annotation won't even be considered when calling from another method of the same class. It doesn't matter what you put there, or even if you leave it out. There still will be a transaction started by method1(), but then you're stuck in that transaction.
If the second method were in a separate class, you could use Propagation.REQUIRES_NEW to have it run in its own transaction, meaning that even if method1() later on failed, any changes in method2() would still have made.
The default transaction propagation of REQUIRED starts a new transaction if none exist, or joins an existing transaction. Again, in the separate class situation it results in the rollback of any changes made in method2() when method1() fails.
Spring boot provides concept of propagation with #Transactions. Propagation level decides that inner transaction should be part of same outer transaction or it should be different isolated one. By default propagation level is REQUIRED which means inner transaction will be part of same outer transaction, so if inner transaction fails whole transaction will get rollback.
Now its important to know that Rollback works for only Runtime exceptions by default. For checked Exceptions you have to specify that explicitly #Transcations(rollbackFor = Exception.class)
So to answer for your question is YES! It does rollback changes made by inner transaction.
this is a typical question:
You should call method2() by self injected object or use this notation, because another ways will call method2 and avoid call proxy object method, which contain all transactional logic.
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with #Transactional. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. #PostConstruct
Nested Transaction behaviour depends on #Transactional parameters. For example - Use PROPAGATION_REQUIRES_NEW for create new transaction for nested methods with #Transactional. See more info in official doc
What happens depends on the chosen transaction propagation. Default is: "REQUIRED" which means that if no transaction exists it will be started.
So in your code method2 will join existing transaction created for method1.
As for your case with both methods in the same class, be careful as this will not work as you expect because of the way Spring proxy objects work.
It depends on your transaction propagation config.
Related official doc is here
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#tx-propagation
Just note the graph, propagation define a transaction's "transaction context".
We're using CDI in our application (NOT EJB). We have a resources layer, a business beans layer and a database handler beans layer. All those beans are #RequestScoped. Right now the resource injects a business bean which in turn injects all dbhandler beans it requires. Since this is CDI and there is no object pooling (at least from what I know) is there a way to decide which beans get injected (and thus created) depending on the method called? For example, I have 2 business bean methods. Method1 uses DAOBean1 and Method2 uses DAOBean1 AND DAOBean2. Right now, even if I only want to use Method1, the business bean will inject both DAO beans. Is there a way to filter injected beans according to the method call? This is important because we have a bean that creates a datasource connection on its #PostConstruct but not all bean methods query the database which means that we create redundant connections when using the bean for non db related methods.
It seems there is no way to have different beans injected according to the method called. Since injections are resolves during the bean creation, the container cannot know which function is going to be called and can't hold on to the injection until we decide. To solve this we either use Programmatic Bean Lookup (using the BeanManager class) to access in-context beans or we can access them through the Instance<T> interface. If we use the Instance interface, we must be careful to not have memory leaks. Why is that? Because every bean injected that way gains the scope #Dependent which means it will be released when the injector class itself is destroyed. If the injector class's scope is for example #ApplicationScoped the bean itself will never be released thus creating a memory leak. In cases like those we use the Instance interface's method called `destroy(myBean).
Example:
#ApplicationScoped
public class MyClass {
#Inject
Instance<MyBean> myBeanInstance;
public void myMethod() {
//...
MyBean bean = myBeanInstance.get();
// Do stuff with bean
myBeanInstance.destroy(bean); //Release the bean otherwise it will hold memory
}
}
I have the following scenario in my code base:
//this bean, which will be injected,
//is not annotated
public class HelperUtil {
//only default constructor with no args
public void doThis(String _in) {
//...
}
public void doThat() {
//...
}
}
In the below class we do the injection:
#Named
#Stateless
public class BusinessManager {
#PersistenceContext(unitName = "default")
private EntityManager em;
#Inject
private HelperUtil helperUtil ;
//...
}
Q1: When is the instance of HelperUtil which will be injected actually initialized by calling the default constructor? Is it done when the first client into which it is injected (like BusinessManager) is instantiated when the app server (in my case JBoss) starts (and that one will be initialized by the container because it is annotated as #Stateless)?
Q2: In the above exhibit, will HelperUtil remain a singleton as long as no client other than the container asks for an instance by calling the constructor directly and not obtaining an instance via DI?
Q3: What is the advantage of using DI and #Inject in this case vs. simply calling the constructor directly (HelperUtil helper = new HelperUtil();)?
It depends, but you can control these event to execute some code, for example:
If you need that your bean is executed when the app start you need to add #Startup annotation to your bean.
If you need to initialize your bean without access to other injected resources you can use the normal constructor.
If you need some method to be executed when the bean is initialized then use the #PostConstruct annotation in the method.
You need to remember that the creation depends on the scope of the bean, in you case, which is a stateless bean, the bean will be created if some client injects it and there are no other instance available, if is singleton then will bean created just once, in general the bean will be created when they are needed (a singleton bean initialize until the first client uses it, or at startup with the annotation)
EDIT:
For the third question, the advantage is that if you use a resource, or other bean inside your HelperUtil, they will be initialized with the proper values, for example, if you use an entity manager, or other beans inside your helper. If your helper will handle just things like static methods or other simple utilities then you are right, the advantage is none and you could simply manage like an static helper class, but if you need EE resources the you need the bean to be managed in order to get all injections and resources loaded
EDIT 2:
After some more years programming and using dependency injection in Java and C# Core, I can add: The question 3 is very open, using DI will allow your code to:
be less coupled, if you change your constructor, you then would have to go searching all the new ObjectModified(oldParams) to add the new parameters
more easy to test, because you can inject "fake objects" as dependencies, avoiding the need to load all the system and prepare the state for the test, for example, if you want to check some code that depends on the current hour, you could connect a fake provider in test mode to give always the same hour, or some sequence
Avoid cyclical dependency, where class A depends on B and B depends on A, normally this is more complex, like
ClasssA -> ClasssB -> ClasssC -> ClasssA
When this dependencies are present, you can start a modification, then modify the class that uses it, and so on... until somehow you find yourself modifying the same class as before!, so you start in a cycle because the communication path between your objects are complex.
When you use DI, this cycles can be detected early on, so you can rethink your architecture to avoid this productivity blackholes
DI is a very powerful tool to keep big projects maintainable, is now present in a lot of environments and frameworks because is very useful, if this still does not convince you, you can try start a project in Spring boot, PlayFramework, Net Core, Java EE, Ruby on Rails.... and many others that have include this as the normal flow and build a medium size app, then try without DI
Background: Everything within CDI operates within a Context. That being said
A managed bean's fields are instantiated, on request. From the spec:
When the container creates a new instance of a managed bean, session bean, or of any other Java EE component class supporting injection, the container must:
Initialize the values of all injected fields. The container sets the value of each injected field to an injectable reference.
What this means is that the first initialization of a dependent bean is when it's first called for, which is when the parent bean is initialized. Now, the JSF #ApplicationScoped has the eager="true" attribute, which allows beans of that scope to be initialized before they're needed by any other part of the application, on startup, EJB #Startup for the same effect on EJBs. CDI beans however, don't have that capability out of the box.
The default scope of CDI beans is #Dependent. What this means is that an injected bean inherits the scope of the injection target (except when the bean has its own scope; in that case, its own scope applies). In your case, HelperUtil is not going to live beyond the lifetime of that EJB, sorta like #RequestScoped
Related
how is the #RequestScoped bean instance provided to #SessionScoped bean in runtime here?
Non-lazy instantiation of CDI SessionScoped beans
JSF Named Bean, Eager application scoped (aka #ManagedBean(eager=true) )
I think its constructor is not called until the method is called like helperUtil.dothat(), its not when its containing bean is instantiated.
About all of the injected fields must be initialized by the container when the managed beans are instantiated like the other answer, its true, but all of the injected fields are injected with proxies so they are not the real objects so the real constructors aren't called.
If its constructor is called when its containing bean is instantiated then how about a #RequestScoped bean inside a servlet for example. The servlet is only instantiated one time but the injected #RequestScoped bean must be instantiated multiple times. If its true then surely the #RequestScoped annotation wouldn't work.
So by simply looking at those CDI annotations intention and name like "request" or "session", we know that the real CDI managed bean objects are made/ instantiated independent of the containing user bean instantiation.
I came across a problem while working with stateless EJB. I want that a particular static method should be used in that EJB but this method is so important and it has static dependency.
As we know instances of stateless session beans are created as per requirements (one or many). So how can I be sure that all the EJB are using a single copy of that static method. I am not sure but I think every different class who use a static method will load different copy of class and then execute a different copy of the static method.
And I can't rely on singleton EJB as it not guaranty that only one copy will remain because if more than one JVM required by server. Different copy of singleton EJB will be in to existence in different JVM.
Thanks in advance.
Static methods are one per class, even if you create thousands of instance of that class all of them will see just one copy of your static method.
Now as per Spec you should not have static methods in your EJB, you should consider moving this as part of utility if you want it static, or else make it non static.
From the Spec:
EE.5.2.3 Annotations and Injection
As described in the following sections, a field or method of certain
container-managed component classes may be annotated to request that
an entry from the application component’s environment be injected into
the class. Any of the types of resources described in this chapter may
be injected. Injection may also be requested using entries in the
deployment descriptor corresponding to each of these resource types.
The field or method may have any access qualifier (public, private,
etc.). For all classes except application client main classes, the
fields or methods must not be static.