@UnitOfWork in cli commands

132 views
Skip to first unread message

Niccolò Giulio Rossetti

unread,
Mar 9, 2018, 8:05:22 AM3/9/18
to dropwizard-user
Hi,

we have a Dropwizard app that includes some cli commands which do not expose a Web API (i.e. there is no Jersey resource).

What I would like to accomplish is to use the annotation @UnitOfWork on some methods invoked by these cli commands that need to connect to the DB via Hibernate. This instead of managing the transaction to the DB ourselves (which we are able to do, tested and works).

My attempt was to instantiate the class where such methods are implemented, with a UnitOfWorkAwareProxyFactory, similarly to what I already successfully done when annotating class invoked by Jersey resources.
Unfortunately, this time I could not make it work and when my DAO tries to create a Hibernate criteria the following exception gets thrown:

Exception in thread "main" org.hibernate.HibernateException: createCriteria is not valid without active transaction
    at org
.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:352)
    at com
.sun.proxy.$Proxy82.createCriteria(Unknown Source)
    at com
.abc.foo.db.MyDAO.getEarliestArrival(MyDAO.java:231)

This confuses me because when I debugged the application, I can see that the UnitOfWork's code gets executed and both an Hibernate session and a Transaction get open. However, obviously when the ThreadLocalSessionContext throws the exception, its real session doesn't have an active transaction..

Are there any known limitation for using the UnitOfWork in cli commands? Or can they be used at all? Do they need some special tuning in respect to what I am used to do with the UnitOfWorkAwareProxyFactory?

Any help is appreciated,
thanks in advance.

Niccolò Giulio Rossetti

unread,
Mar 15, 2018, 9:34:22 AM3/15/18
to dropwizard-user
I eventually made it work and I will share the solution I adopted.

The code I worked on implemented ConfiguredCommand inside a Dropwizard application. In order to connect to the DB, its run method configured Hibernate. This was done in 3 steps: 1) set up of the HibernateFactory and create an HibernateBundle, 2) configure Hibernate properties  (configuration.getDataSourceFactory().getProperties().put(..)) and 3) initialization by using the hibernateBundle run method which received a newly created Environment object. The command's code then had to manage the transactions and commits explicitly instead of using @UnitOfWork.

It worth noting that another HibernateBundle was created by the application itself before running the command code. Either this or the initialization of Hibernate in the cli's run method altogether might have been the cause of the inability to use the @UnitOfWork annotation.

What I figured out is that Dropwizard provides another abstract class, EnvironmentCommand, whose constructor takes an Application instance other than the command name and description (as for the ConfiguredCommand). Its javadoc drily describes: "A command which executes with a configured {@link Environment}." . By extending such a class and passing to it the Application instance of which the command is part, the @UnitOfWork is able to use the HibernateBundle. As usual, this is possible only if the classes using such annotation are instantiated by a UnitOfWorkAwareProxyFactory.

My understanding is that the UnitOfWork and its factory uses the environment of the main application and wouldn't recognize other environement and bundles instantiated within the command. As a final note, I am not sure whether the EnvironmentCommand comes with components unnecessary for the execution of our command and if it were possible and recommendable to twist the previous ConfiguratedCommand approach so that the UnitOfWork used the new Environment and bundle.

Alex Kudlick

unread,
Sep 8, 2021, 7:40:02 PM9/8/21
to dropwizard-user
Another approach is to use UnitOfWorkAwareProxyFactory to create the command objects and annotate the command object methods with @UnitOfWork. In general, UnitOfWorkAwareProxyFactory can create proxy objects will all the UnitOfWork configuration as used in resources.
Reply all
Reply to author
Forward
0 new messages