Alex Mi
Alex Mi

Reputation: 1459

Usage of @Stateless and @Transactional on a POJO class - when and why?

I have a developer in my team who uses both of the annotations @Stateless and @Transactional on POJO classes that do not need any of these to work correctly. Example:

@Stateless
@Transactional(Transactional.TxType.REQUIRED)

public class ObjektAnlegenService {

    public Home setImagesToHome(Home home, ImagesUploadHelper imgUpldHelper) {
        Objects.requireNonNull(home, "Home is Null!");
        Objects.requireNonNull(imgUpldHelper, "ImagesUploadHelper is Null!");
        String mainImage = null;
        for (Image savedImage : imgUpldHelper.getImagesSaved()) {
            if (savedImage.isMainImage()) {
                mainImage = savedImage.getSimpleFileName();
            }
            savedImage.setHome(home);
        }
        home.setHomeImages(imgUpldHelper.getImagesSaved());
        home.setMainImageTabl(mainImage);
        return home;
    }

    public String[] getPlzOrtDetails(String plzOrtInput) {
    
        int indexOfComma = plzOrtInput.indexOf(Constants.COMMA);
        indexOfComma = indexOfComma == -1 ? plzOrtInput.length() : indexOfComma;
        
        String[] plzOrt = PlzOrtUtils.getPlzOrt(plzOrtInput.substring(0, indexOfComma));
        return plzOrt;
    }
}

My questions:

1.) @Transactional only makes sence, when the POJO class (or its methods) shall work with a transactional datasource, such as database or a transactional web-service. Otherwise it only adds a load to the server, right?

2.) @Stateless only makes sence when we want the JEE server container to manage the CDI (context and dependency injection) of the POJO class. But @Stateless adds an additional load to the JEE Server, because @Stateless beans are insantiated, pooled and kept in JNDI, right?

Then: if a POJO can exist and work as a singleton (as is the case with ObjektAnlegenService above), isn't it better to design it as a singleton, instead of a @Stateless?

Upvotes: 0

Views: 783

Answers (1)

Nikos Paraskevopoulos
Nikos Paraskevopoulos

Reputation: 40308

@Stateless marks the class as a stateless session EJB. As such it lives and is managed by the EJB container (so, right, pools, JNDI etc). Session EJBs are also visible to the CDI container and available for injection with @Inject, but it is the EJB container that is responsible for them. So, this is not exactly as you say "

So, to answer the question whether you want the class annotated with @Stateless, you need to decide whether you need those services. If not, @ApplicationScoped will do.

@Transactional instructs the CDI container to activate transactions for this component. If you decide that this component needs to be an EJB, remember that the EJB container activates transactions by default to session EJBs. So, the extra @Transactional annotation is redundant.

You may add transaction demarcation annotations in every method to explicitly state that it needs to be transactional. I would prefer to demarcate the transactions at the top level of the business layer and only where needed, but this is only my opinion.

EDIT-CLARIFICATION: Would a singleton POJO be better? By singleton POJO I assume you mean annotating the class with javax.inject.Singleton, not javax.ejb.Singleton, which is an EJB. If so, bear in mind that javax.inject.Singleton defines a pseudo-scope and as such the bean is not eligible for interception. Since the @Transactional annotation works by defining an interceptor, it would not work for @javax.inject.Singleton beans. That is why I mentioned @ApplicationScoped above. This is effectively a singleton (as in the singleton pattern), but is eligible for interception, so all expected facilities of the CDI container apply.

Upvotes: 2

Related Questions