samedi 23 mai 2015

Insert programmatically generated classes into application deployment before ejb class loading, is it possible?

Despite my efforts on searching for an answer on that topic, I ended up empty-handed. What I want to know is if it is possible (or if it has been tried before) to generate a class programmatically BEFORE an EJB/CDI implementation starts searching for annotated classes. If the solution I'm about to ask for doesn't exist, I may create it myself. What I want is to use the Java EE 6/7 stack to my advantage and reduce the amount of similar (and boilerplate) code I need to create for some common tasks.

Better than just ask, I will show an example of what I want to achieve. Suppose you have a business entity such as this:

@Entity
public class User {

    @Id
    private Long id;

    @NotNull
    private String login;

    /* ... */
}

And suppose I have a business layer interface for said entity:

@Local
public interface UserService {

    User findByLogin(String login);
}

To avoid having to implement trivial methods like those, I want to annotate the entity like...

@Entity
@BusinessLayer(
    name = "Users",
    ejbInterfaces = { UserService.class },
    ejbType = EjbType.STATELESS,
    persistenceContextUnitName = "users-PU"
)
@NamedQueries({
    @NamedQuery(
        name = "User.findByLogin",
        query = "select o from User o where o.login = :login"
        hints = {
            @QueryHint(name = BusinessLayerQueryHints.QUERY_TYPE, value = "entity_search")
        }
    )
})
public class User {
    /* ... */
}

... And a possible runtime may programmatically create a class, be it by proxy or bytecode, such as:

@Stateless(name = "users")
public class Users__RuntimeImpl {

    @PersistenceContext(unitName = "users-PU")
    private EntityManager em;

    public User findByLogin(String login) {
        User user = null;
        boolean validUserLogin = /* validating a single property */;
        if (validUserLogin) {
            // Because of the entity_search hint
            TypedQuery<User> query = em.createNamedQuery("User.findByLogin");
            query.setParameter("login", login);
            user = query.getSingleResult(); // May be exchanged for a getResultList().get(0);
        }
        return user;
    }
}

The application server would be able to load Users__RuntimeImpl and use it for injection, just like what is done with any other "statically" created class.

I guess something like ShrinkWrap is what I'm looking for, but I'm not entirely sure (e.g. guaranteeing that ShrinkWrap kicks in before deployment, and that the dynamic JAR gets deployed as a dependency of the application). Also, I'm not sure about the feasibility of such a runtime in a web profile.

I'm not afraid of delving into implementation-specific application server information, as long as such a library is able to interoperate with Java EE technologies.

Aucun commentaire:

Enregistrer un commentaire