Java design issue where behavior is attached to annotations - java

Let say I use JPA by using #transactions annotations.
So to have any method run under a transaction I add a #transaction annotations and BINGO my method run under a transaction.
To achieve the above we need have a interface for the class and the instance is managed by some container.
Also I should always call the method from interface reference so that the proxy object can start the transaction.
So My code will look like:
class Bar {
#Inject
private FooI foo;
...
void doWork() {
foo.methodThatRunUnderTx();
}
}
class FooImpl implements FooI {
#Override
#Transaction
public void methodThatRunUnderTx() {
// code run with jpa context and transaction open
}
}
interface FooI {
void methodThatRunUnderTx();
}
Well and Good
Now let say methodThatRunUnderTx does two logic operations
[1] call some service(long request/response cycle let say 5 sec) and fetch the results
[2] perform some jpa entity modifications
Now since this method call is long and we don't want to hold the transaction open for long time, so we change the code so that [2] happens in separate tx and methodThatRunUnderTx doesnt run in transaction
So we will remove the #Transaction from the methodThatRunUnderTx and add another method in class with #transaction let say new methods is methodThatRunUnderTx2, now to call this method from methodThatRunUnderTx we have to inject it into itself and add a method to interface so that the call happen through proxy object.
So now our code will look like:
class Bar {
#Inject
private FooI foo;
...
void doWork() {
foo.methodThatRunUnderTx();
}
}
class FooImpl implements FooI {
#Inject
private FooI self;
#Override
//#Transaction -- remove transaction from here
public void methodThatRunUnderTx() {
...
self.methodThatRunUnderTx2();// call through proxy object
}
#Override
#Transaction //add transaction from here
public void methodThatRunUnderTx2() {
// code run with jpa context and transaction open
}
}
interface FooI {
void methodThatRunUnderTx();
void methodThatRunUnderTx2();
}
NOW The Problem
We have made methodThatRunUnderTx2() to be public through interface.
But it is not what we want to expose as our api of FooI and not meant to be called from outside..
Any suggestion to solve it ?

That's why modern containers don't require any interface to be implemented - proxies are then created by dynamic subclassing or bytecode instrumentation is used.
So, the solution to your design issue is simple: Implement a helper class containing the transactional method and inject it to the class implementing the interface (and to any other class that can benefit from it).

Following the Interface Segregation Principle, separate the two logic operations into two interfaces: a fetcher and a modifier. Inject both into class Bar. This allows the two logic implementations to change independently of each other, for example allowing one to be transactional while the other is not. The second interface need not be a public class.

The question is a very valid one on handling the Transaction part. However, if you are trying to hide one functionality over other, you need to consider these :
OPTION 1 :
Considering - You would need to expose the method that does the whole functionality required by the caller
In this case of transaction handling, I would suggest you to keep the transaction open for the time being till it completes
OPTION 2:
Considering - You would need to efficiently manage transactions
Split the interface's methods based on Functionality IModifyFoo and ISelectFoo that does modify and select respectively and implement the methods and annotate with #Transactional on required methods
Interfaces are designed to be public that means that you need to be aware of what you need to expose to external world. In this scenario, you are posed to choose Principle over the technical challenge.
I can just think of these options and we are trying to address your technical challenge here that resides on basics of java. Good one to think about.

As you said, if you call a method on the same bean it'll not be proxied therefore no transaction management will happens, to solve it you can you Bean Managed Transaction where you manually start and stop the transaction:
class FooImpl implements FooI {
#Resource
private UserTransaction userTransaction;
#Override
//#Transaction -- remove transaction from here
public void methodThatRunUnderTx() {
...
self.methodThatRunUnderTx2();// call through proxy object
}
#Override
//#Transaction -- remove transaction from here too, because now you'll manage the transaction
public void methodThatRunUnderTx2() {
userTransaction.start();
// code run with jpa context and transaction open
userTransaction.commit(); // Commit or rollback do all the handling, i'm not writing it because its just an example
}
}
That way you are not exposing anything extra to public api, but you'll have a little extra code to manage the transaction.

if you want that methodThatRunUnderTx2 does not become public make it a private method and remove #Override annotation and remove it from interface.

You have to accept that transaction-based annotations won't work on private methods. So you simply cannot hide (make private) a method that is supposed to be a subject of that kind of annotation.
You can get rid of interfaces (i.e. #LocalBean in EJB world), but still, you cannot use private method...

For sure the solution for this problem are acpects. They would allow to get rid of self.methodThatRunUnderTx2() method call from the body of public void methodThatRunUnderTx(). Most probably the answer for this question could help you: Aspectj and catching private or inner methods
I'm not sure however if aspects are not too big gun for this problem, as they increase complexity and readability of code. I would rather think about changing architecture of your code in such a way, that your problem would not matter.

Related

Spring #Transactional - can one test the number of transactions?

I have an api class annotated with #Transactional as shown. Some subset of the methods are further annotated with readOnly=true. When writing tests is there any way to verify the number of transactions that actually take place? Consider if the delete method implementation called the exist method - then in a test calling delete only one transaction should occur. However, if the test itself calls the exist method prior to calling delete then 2 transactions should take place.
#Transactional
public class AnApi {
public AnEntity create(EntityData data) {...}
public void delete(Long id) {...}
#Transactional(readOnly = true)
public boolean exists(Long id) {...}
}
While I know the framework functions this way, it is preferable to put in tests to detect any future changes and avoid potential surprises.
That shouldn't be too difficult.
Spring uses a PlatfromTransactionManager for managing transactions.
If you register a wrapped transaction manager that implements this interface by delegating to the actual transaction manager, you should be easily able to count the invocations/number of transactions returned.

How to select JDBC / JPA implementations at run time?

I'm writing an application meant to manage a database using both JDBC and JPA for an exam. I would like the user to select once at the beginning the API to use so that all the application will use the selected API (whether it be JPA or JDBC).
For the moment I decided to use this approach:
I created an interface for each DAO class (e.g. interface UserDAO) with all needed method declarations.
I created two classes for each DAO distinguished by the API used (e.g UserDAOImplJDBC and UserDAOImplJPA). Both of them implement the interface (in our case, UserDAO).
I created a third class (e.g. UserDAOImpl) that extends the JDBC implementation class. In all my code I've been always using this class. When I wanted to switch to the JPA I just had to change in all DAO classes the extends ***ImplDAOJDBC to extends ***ImplDAOJPA.
Now, as I'm starting having many DAO classes it's starting being complicate to modify the code each time.
Is there a way to change all extends faster?
I was considering adding an option in the first screen (for example a radioGroup) to select JDBC or JPA. But yet I have no idea how to make it work without having to restructure all code. Any idea?
Use a factory to get the appropriate DAO, every time you need one:
public class UserDaoFactory {
public UserDao create() {
if (SomeSharedSingleton.getInstance().getPersistenceOption() == JDBC) {
return new UserDAOImplJDBC();
}
else {
return new UserDAOImplJPA();
}
}
}
That's a classic OO pattern.
That said, I hope you realize that what you're doing there should really never be done in a real application:
there's no reason to do the exact same thing in two different ways
the persistence model of JPA and JDBC is extremely different: JPA entities are managed by the JPA engine, so every change to JPA entities is transparently made persistent. That's not the case with JDBC, where the data you get from the database is detached. So the way to implement business logic is very different between JPA and JDBC: you typically never need to save any change when using JPA.
You got 1 and 2 right, but 3 completely wrong.
Instead of having Impl extending one of the other implementations, choose which implementation to initialize using a utility method, for example. That's assuming you don't use Dependency Injection framework such as Spring.
UserDAO dao = DBUtils.getUserDAO();
public class DBUtils {
public static boolean shouldUseJdbc() {
// Decide on some configuration what should you use
}
public static UserDAO getUserDAO() {
if (shouldUseJdbc()) {
return new UserDAOImplJDBC();
}
else {
return new UserDAOImplJPA();
}
}
}
This is still jus an examle, as your DAOs don't need to be instantiated each time, but actually should be singletons.

Can we mock a method in service while testing the service itself?

I am working on a project where I am using MyBatis annotations as persistence framework. Therefore, I have to create an interface for the 'mapper' and compose the mapper in the service like :
class XYZServiceImpl{
public XYZMapper getXYZMapper(){
return SessionUtil.getSqlSession().getMapper(XYZMapper.class)
}
}
Now while unit testing the service with Mockito, I am trying to inject a mock for the mapper. But since I am injecting mock in an instance of XYZService, how can mock a method of the service itself, in this case getXYZMapper() is what I am trying to stub. Although I have got a solution of creating the instance XYZMapper in the service and not call on demand like the above code does something like :
Class XYZServiceImpl{
XYZMapper mapper;
public void useXYZMapper(){
mapper = SessionUtil.getSqlSession().getMapper(XYZMapper.class);
}
}
But that would bring a lot of code changes (ofcourse I can refactor) but is there a way to achieve without having to make code changes?
Also what would be a 'purist' way to have a mapper instance in the class is it the method 1 that is better than method 2 in terms of performance?
EDIT : Here XYZMapper is an interface. Something like :
public interface XYZMapper{
#Select("SELECT * FROM someclass WHERE id = #{id}")
public SomeClass getSomeClass(int id);
}
EDIT : I am facing a similar situation but with a variance that I have a service that I do want to test like XYZServiceImpl. Now it has a method getXYZDetails() which has a lot of business logic handled within the service. Now if getXYZDetails looks like the following :
public XYZDetails getXYZDetails(int id){
XYZDetails details = new XYZDetails();
details.set1Details(fetchSet1Details(id));
//Perform some business logic
details.set2Details(fetchSet2Details(id));
if(details.set2Details() != null){
for(int i = 0; i < details.set2Details().size(); i++){
flushTheseDetails(i);
}
}
.
.
}
Kindly notice that fetchSet1Details(), fetchSet2Details(), flushTheseDetails are public service, public and private service respectively.
I want to know of a method that can mock/stub these methods while testing getXYZDetails() thus enabling me to
There are several options you can use.
Inject dependency
This works only for simple methods like getXYZMapper when method only returns external dependency of you object. This may require to create new XYZServiceImpl instances if for example mapper is bound to connection which is opened per request.
Encapsulate method behavior in object
Another way to achieve similar result is to use a factory or service locator
like this:
public class XYZServiceImpl {
public XYZServiceImpl(XYZMapperFactory mapperFactory) {
this.mapperFactory = mapperFactory;
}
public XYZMapper getXYZMapper() {
return mapperFactory.getMapper();
}
}
This will allow you easily substitute factory in test with implementation which returns mock mapper.
The similar approach can be used for other methods fetchSet1Details, fetchSet2Details, flushTheseDetails that is moving them to other class or classes. If the method contains complex (and may be loosely related) logic it is a good candidate to be moved in separate class. Think about what these methods do. Usually you can move some essential and unrelated part of them to other class or classes and this makes mocking them much easier.
Subclass
This is not recommended but in legacy code sometimes is very helpful as a temporary solution.
In your test subclass you class under test and override methods you need:
#Test
public void someTest() {
XYZServiceImpl sut = new XYZServiceImpl() {
public XYZMapper getXYZMapper() {
return mapperMock;
}
public Whatever fetchSet1Details() {
return whateverYouNeedInTest;
}
}
sut.invokeMethodUnderTest();
}
The only thing you may need to do is to change access modifier of private method to package-private or protected so you can override them.
Spying
This method in also discouraged but you can use mockito spies:
XYZServiceImpl realService = new XYZServiceImpl();
XYZServiceImpl spy = Mockito.spy(realService);
when(spy.fetchSet1Details()).thenReturn(whaeveryouneed);
when(spy.getXYZMapper()).thenReturn(mockMapper);
spy.methodUnderTest();
I would suggest the "purist" way of doing this is to accept an XYZMapper instance in your constructor and store it in a local field.
In production use, you can pass an e.g. SQLXYZMapper, which will interact with your database. In test use, you can pass in a mocked object that you can verify interactions with.

Understanding Service and DAO layers

I was asked to create documentation of classes in the business logic module of a project. I noticed that there was a pattern on how the classes where created. The pattern looks like this
public class AModel(){
//fields
//getter and setters
}
public class AService(){
public void processA(AModel model){
//creates instance of AModel, assigns values to fields
//calls ADaoService methods
}
}
public class ADaoService(){
//has methods which call ADao methods
//sample
public AModel retrieveById(long id){
log.debug(...);
return (ADao.retrieveById(id));
}
}
public class ADAo(){
//has entityManager and some query
public AModel retrieveById(long id){
return((AModel) entityManager.find(AModel.class, id));
}
}
What I don't understand is why does AService calls ADaoService methods instead of just calling ADao methods since ADaoService methods are just calling ADao methods. It seems to me that ADaoService was just a waste of code. They are usign Hibernate and JBoss server. I'm just new to this type of architecture. Hope someone can help me understand. Thanks.
Well, if ADaoService is doing nothing but delegating calls to ADao then clearly you're right - it has no existence justification at the moment.
Regarding future justifications, well, AFAIK, the typical layering does not include ADaoService layer. Where I work we don't have it. Never seen it in Hibernate docs...
Either your architects were generous with layers or they had some non-typical scenario in mind.
If there's no current usages of the layer and no clear future usages - you're better off without it.

Obtaining a Hibernate transaction within a Spring class

I am working on a program that uses Spring and obtains Hibernate transactions transparently using a TransactionInterceptor. This makes it very convenient to say "when this method is invoked from some other class, wrap it in a transaction if it's not already in one."
However, I have a class that needs to attempt a write and must find out immediately whether or not it has succeeded. While I want two methods anyway, I was hoping that there was a way to keep them in the same class without needing to explicitly create an transaction procedurally. In effect, I'd like something like this:
public void methodOne() {
//..do some stuff
try {
transactionalMethod();//won't do what I want
} catch(OptimisticLockingFailure e) {
//..recover
}
}
#Transactional
public void transactionalMethod() {
//...do some stuff to database
}
Unfortunately, as I understand it, this wouldn't work because I'd just be directly calling transactionalMethod. Is there a way to ask Spring to call a local method for me and wrap it in a transaction if needed, or does it have to be in another class that I wire to this one?
Define an interface which the class implements which does the transactionalMethod(); use dependency injection to set the class' value of that to its own implementation; in your bean factory, allow Spring to insert an Around aspect around that interface implementation. That should work for your needs.
If you want the transactionalMethod to be part of it's own transaction and not simply join onto the transaction that is already active you have to set the propagation to REQUIRES_NEW. Like so
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void transactionalMethod() {
//...do some stuff to database
}
You should also check that your transaction manager supports this propagation. the means that transactionalMethos is completely seperate from the other transaction that it was called from and it will commit / rollback completely seperately as well.

Categories