I'm developing a JEE application where each request done to "facade" beans should run a single transaction.
Basicly, in each method, I could do it like this:
#Override
public void updateSalaries(float factor)
{
initializeTransaction();
// Actual business code...
commitTransaction();
}
Where ùpdateSalaries()is a method invoked by the client, and whereinitializeTransaction()andcommitTransaction()` respectively take care of getting/starting/committing/rolling back (if necessary) the transaction.
Unfortunately, the transaction management should be more transparent: something developers should not care about when writing business methods.
Therefore, some way to "decorate" these business methods would be nice, but I can't think of a possible way to do that.
Another possible solution I thought of would be to handle it in a central DataAccessBean class, where I would start the transaction on #PostConstruct and commit it on #PreDestroy:
#Stateless
public class DataAccessBean implements IDataAccessBean
{
#PostConstruct
public void initializeTransaction() { /* ... */ }
#PreDestroy
public void endTransaction() { /* ... */ }
#Override
public <T implements Serializable> T getObjectById(
Class<T> objectType, Object key) { /* ... */ }
#Override
public void saveObject(Serializable object) { /* ... */ }
}
I'm not sure though, if I can rely on that mechanism. An important question would also be, what type of bean I'd need: I doubt a stateful bean would be suitable as the transaction is per-request and not per-session. Maybe a stateless bean would be a good option, but AFAIK a stateless bean might not be destroyed when a request completes (if it resides in a stateless bean pool).
Two little constraints:
The solution should not depend on a particular non-standard framework or JEE-server
The solution should be compatible with JEE 6 and JEE 7
Thanks for the suggestions.
What you need is addressed by Java Transaction API (JTA). From the JEE6 Tutorial (Part VIII - Chapter 42):
The Java Transaction API (JTA) allows applications to access transactions in amanner that is
independent of speciic implementations. JTA speciies standard Java interfaces between a
transactionmanager and the parties involved in a distributed transaction system: the
transactional application, the Java EE server, and themanager that controls access to the shared
resources afected by the transactions.
You want to use the Container-Managed Transaction. In this strategy you just need decorate the beans/methods with the appropriate transaction attribute i.e.:
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void myMethod() {
...
}
The design of your service layer must carefully address the transaction life cycle in case your have services of services (nested service calls).
Related
If I have a stateful class that requires a utility-like stateless class to perform an operation on it. These stateful classes are kept in a list in a container (stateful) class. This is what I would do with plain Java:
class Container {
List<Stateful> sfList;
}
class Stateful {
List<String> list;
void someMethod() {
list.add("SF");
Stateless.foo(this);
}
class Stateless {
public static void foo(Stateful sf) {
sf.getList().add("SL");
}
}
and inside main this is the procedure:
Stateful sf = new Stateful();
sfList.add(sf);
sf.someMethod();
Now with JavaEE CDI I would do:
class StatefulBean {
List<String> list;
#Inject
StatelessBean slsb;
void someMethod() {
list.add("SF");
slsb.add(this);
}
#Stateless
class StatelessBean {
public void add(StatefulBean sfsb) {
sfsb.add("SL");
}
}
In this case all StatefulBean could access a shared pool of StatelessBean with no concurrency issues and it will scale properly with requests.
However, since Stateful is not a managed bean I can't inject into it and so I used the utility class instead. Also I'm creating Stateful with a constructor so I can't inject into it the stateless bean (I will get a NPE using it).
My questions are:
Are there concurrency and scalabilty differences between the stateless injection approach (provided it would work) and the utility class approach?
How can I make the EE injection approach work?
Are there concurrency and scalabilty differences between the stateless injection approach (provided it would work) and the utility class approach?
Yes there are, primarily around the loss of management. The way you're instantiating Stateful on every invocation of the method, there's no pooling involved. This is going to lead to you creating more instances than you probably need.
Another loss is on the scalability side. Where the container will manage the passivation and activation of your stateful bean in a distributed environment, the manual approach will see to it that you manage your own activation and passivation.
Since Stateful is not a managed bean..
Incorrect. According to the CDI Spec, any java class that meets the listed criteria (in your case, a default no-arg constructor) is a managed bean. That means that you could #Inject StatelessBean into Stateless and the container would oblige. To allow this level of management, you'll need to set bean-discovery-mode=all in your beans.xml.
Even with the (apparently needless) circular reference, normal Java concurrency rules apply: as long as the state that you're manipulating is not static or in a static class, you're threadsafe. Each threaded call to that static method still operates on a separate stack, so no problems there.
How can I make the EE injection approach work?
If you need on-demand instantiation of Stateless(or any other bean really), use the CDI Instance to programmatically obtain a managed instance of any class you want. You can now add something like this to Container:
#Inject #Dependent Instance<Stateful> stateful;
#PostConstruct
public void createStateless(){
//instantiate sfList;
sfList.add(stateful.get()); //execute as many times as you need
}
Is this code copmliant to Java EE spec and can be used?
#Stateless
public class SomeBean {
#Inject
protected TransactedRunner txRunner;
public void someFunc() {
txRuner.run(new Runnable(){
Connection c = ds.getConnection();
//do jdbc stuff or jpa stuff
//close everything etc.
});
}
}
#Stateless
public class TransactedRunner {
#TransactionAttribute(REQUIRES_NEW)
public void run(Runnable r) {
r.run();
}
}
In this case a new transaction should be started and every thing that will be done in runnable will be transacted. Is that right? Or there is some trick in which I should suffer from EE?
This should work as intended. But be aware, that multiple calls of txRunner.run during one service call might lead to inconsistent data if anything happens between or during those calls, like connection-timeout, transaction-timeout, or the node dies or something. And the calling transaction (if there is any) might not see the changes done during the call until it itself has been committed.
There is an annotation in JavaEE6 called #Asynchronous which is specifically for this purpose. Here is the official tutorial: http://docs.oracle.com/javaee/6/tutorial/doc/gkkqg.html
#Stateless
public class SomeBean {
#Inject
private SomeBean self;
public void someFunc() {
self.doSomething();
}
#TransactionAttribute(REQUIRES_NEW)
#Asynchronous
private void doSomething() {
Connection c = ds.getConnection();
//do jdbc stuff or jpa stuff
//close everything etc.
}
}
Also it's not allowed to create or manage Threads within a EJB Container. Check out: http://www.oracle.com/technetwork/java/restrictions-142267.html#threads
Why is thread creation and management disallowed?
The EJB specification assigns to the EJB container the responsibility for managing threads. Allowing enterprise bean instances to create and manage threads would interfere with the container's ability to control its components' lifecycle. Thread management is not a business function, it is an implementation detail, and is typically complicated and platform-specific. Letting the container manage threads relieves the enterprise bean developer of dealing with threading issues. Multithreaded applications are still possible, but control of multithreading is located in the container, not in the enterprise bean.
Method "run" will be executed in transaction, that's true. But it has nothing in common with threading or using executor. In your example, the calling thread will execute your "run" method. Runnable interface itself won't create a separate thread for you.
If you need this call to be executed by separate thread, you can use asynchronous calls, or, starting from EE7, a ManagedExecutorService is available:
http://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/ManagedExecutorService.html
How should I create a controller which is thread safe?
As per the best practice controllers are singleton.
Consider the below code in which im storing user data through a autowired service Object ,which makes my code stateful.
How would i make the below code thread safe.
#RestController
class ApiController {
#Autowired
IDbService< User > iDBService;
#RequestMapping(value = "/api/adduser", method = RequestMethod.POST)
public ResponseEntity<User> createUser(#RequestBody User user){
User savedUser=iDBService.create(user);
return new ResponseEntity<User>(savedUser, HttpStatus.CREATED);
}
Here is my Service implementation.
I have shared variable in my service
public class IDbServiceImpl<T> implements IDBService<T>{
#Autowired
GenericRepository<T, Serializable> genericRepository;
#Override
public T create(T object) {
return genericRepository.save(object);
}
}
Your controller is a singleton by default and your service is singleton by default too.
Therefore in order to make them thread safe you have to make sure that the operations that take place inside the service must be thread safe, in case of changing the state of an object inside the service ie. a list.
In case of using a rdbms then you have a transaction related problem.
If you use spring and Jpa, the transaction manager will take care for your updates provided that you use #Transactional. In case of plain jdbc method then you can either use pure jdbc and do the transaction handling on your own or use spring-jdbc that comes with a transaction manager.
If you want the database rows not to be changed in case of a write in progress then you have to take into consideration row-locking related mechanisms. – gkatzioura Feb 7 at 15:23
In case of JPA using #Transactional will do the work. However depending on your application you might have to consider locking. Check this article on locking with jpa.
Controllers are singletons, therefore they should be implemented in a thread safe manner.
Design your application in a way that controllers are stateless. Add transactional support in your #Repository layer.
Example:
public class GenericRepository<T, Serializable> {
#Transactional
public void save(T object) {
// save user
}
}
You could use Spring declarative transaction management mechanism. The #Transactional annotation itself defines the scope of a single database transaction.
Your controller looks thread safe. As there is no instance variable storing the state. User object will be different for each request and will be resolved by the MVC framework.
I have a moderate sized Java EE 6 project that uses several EJBs, including one which sole purpose is managing database calls through JPA. My question is what is the best way to add a new class that does some random bit of functionality and then calls the database access EJB to persist the data from this class.
Does this new class have to be an EJB if it needs access to annotations and injections? Does it have to be an EJB if it has to be deployed with the rest of the project?
I was told that if you want to add a new logic class to the project it either has to be an EJB or you can remotely integrate it using JNDI to access EJB elements and create some kind of client interface. Right now my new class is just a POJO but it's not able to access the EJB functionality.
What should I do in general?
EDIT: Please note my question IS NOT about database access. That's just an example I'm using. My guestion is more broad. I want to know how to access EJB methods from other classes I create. From one EJB to another you can simply inject the other EJB since they're both container managed. But say I create another class in the same package as the EJBs how might How can I access those methods? Is it possbile? What is the best practices here.
Right now I have a class that is taking twitter feed data from a URL it then parses the JSON and returns a string of the top 10 entries. I want to call my EJB that manages database access and pass that string to its corresponding method but I cannot do that because my class is not also an EJB.
EJBs are generally used to implement services of any kind. They integrate really well with JPA so are often used for DB access, but that's not their only usage.
What EJBs are typically not suited for is modeling data. I.e. they should be the verbs in your application, not the nouns. The following is thus wrong:
#Stateless
#Entity
public class CreditCard { // silly, don't do this!
#Id
Long id; + getters/setters
Data expiration date; + getters/setters
}
The following is better, it's a service that when your application starts up fetches some quote data from somewhere:
#Singleton
#Startup
public class QuoteFetcher {
private List<Quote> quotes; // + getter
#PostConstruct
public fetchQuote()
quotes = SomeUrlBuilder.someUrl().getQuotes();
}
}
The following is the obligatory DAO example:
#Stateless
public class JPAInvoiceDAO implements InvoiceDAO {
#PersistenceContext
private EntityManager entityManager;
public Invoice getById(Long invoiceId) {
return entityManager.find(invoiceId, Invoice.class);
}
// More DAO methods
}
The following shows how declarative security is used, and how a bean looks up something that has been externally mapped into its private context (ENC):
#Stateless
public class TokenFetcher
#Resource
private SessionContext sessionContext;
#RolesAllowed("SYSTEM")
public Token getToken() {
return (Token) sessionContext.lookup("token");
}
}
The second part of the question seems to be how to use these beans in your code. There are basically four methods:
Injection in managed beans
Bootstrapping via JNDI
Automatically called at startup
Automatically via a timer
Injection is the easiest way, but only managed beans are injection candidates (basically meaning the Java EE framework creates the bean, and you don't use new() to instantiate it).
E.g. Injection:
#ManagedBean
public class InvoiceBacking {
private Long invoiceId; // + getter/setter
private Invoice invoice; // + getter
#EJB
private InvoiceDAO invoiceDAO;
#PostConstruct
public void init() {
invoice = invoiceDAO.getById(invoiceId);
}
}
(also see Communication in JSF 2.0#Processing GET request parameters)
Bootstrapping via JNDI:
public class SomeQuartzJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
InvoiceDAO invoiceDAO = (InvoiceDAO) new InitialContext().lookup("java:global/myApp/myEJB/InvoiceDAO");
List<Invoice> openInvoices = invoiceDAO.getAllByOpenStatus();
// verbose exception handling and closing JNDI context omitted for brevity
}
}
The #Singleton bean showed earlier was an example of how the Java EE framework calls your code itself at startup. For the automatic timer you would use the #Schedule annotation on a bean's method.
I'm trying to get the clear picture of how this works:
-What is the advantage of using DAO class with DAO interface?
-How to handle Hibernate exceptions i.e
public String doSomething(){
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Query query = session.createQuery("");
Object o = query.uniqueResult();
session.close();
return "success";
}
I'm not "forced" to try/catch, so how do I catch/intercept any exceptions that may occur?
-Is opening session everytime for new DAO method more expensive than getting the current session? Should I close the session if I use get?
Question Update:
I have #Service annotation in my service classes and for each method using dao interface I've got #Transactional above. Also I've added #Repository to all my DAO classes
Update II:
I'm considering opening bounty for this questions because I want to know more details and this time I'll provide some.
Spring context
Controller
Service Interface
Service Implementation
DAO interface
DAO implementation
So I want to utilize spring MVC as much as possible, how do I make session opening/closing handled by #Transactional?
How do I catch the exceptions(i.e. non existing record or database failed) if any.
What I'm doing wrong? Can anyone suggest some improvements?
A few things on the hibernate session side...
1.) I would take a look a integrating Spring's transaction management into your project. This way you don't have to worry about opening and closing your session's because Spring will handle this for you with intercepts using the #Transactional annotation.
2.) If spring is handling your transactions you won't have to worry about doing the finally calls to make sure everything is closed or rolled back.
3.) If you decide not to use Spring to manage the sessions you should not keep it open for any extended period of time but again, if you use Spring you don't have to worry about it.
As far as the interface on the DAO classes i offer this...
1.) It is considered a good design practice to code to interfaces (see comments left below) and here are a few good reasons why.
lets say you have a...
public interface ShoppingCartService{
public void doStuff(Object obj);
}
You could expose this service as a servlet and deal with the just the 'contract' your interface creates or even hide the fact your using Hibnerate, JDBC or anything else...
#Service
public class PetShopShoppingCartService implements ShoppingCartService{
#Transactional(propagation=Propagation.REQUIRED)
public void doStuff(Object obj){
//The Pet Shop service impl uses hibernate!;
}
}
or...
public class DrugStoreShoppingCartService implements ShoppingCartService{
public void doStuff(Object obj){
//The Drug Store service uses JDBC;
}
}
Or even...
public class NextBigThingShoppingCartService implements ShoppingCartService{
public void doStuff(Object obj){
//do stuff with next big thing;
}
}
I think you get the picture. If you developing public api's or exposing services this becomes pretty important.
Lastly, another good reason to have the interfaces is with working in a team of more than a couple developers. You can quickly stub out an interface, check-in and tell everyone else that this is how it's going to look. This allows them to see what's important and even mock their own impl if they need to (ThingServiceMockDataImpl)
Just because you're not forced to catch exceptions when using Spring's HibernateTemplate doesn't mean that they will not get thrown. They will just be RuntimeExceptions instead of checked exceptions. Also, getCurrentSession() does not open a new session each time you call it, it returns the local Thread's Session.
There are lots of advantages, including lack of code coupling, encapsulation, and transaction demarcation for using the DAO strategy instead of putting your data access code directly into your controller. See http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html for more info.