How to get service according value with pattern? - java

I want according to role value, to get associated service, like
LogisticsUserEntity user = this.getLogisticsUserById(userId);
UserDealService userDealService = getUserDealService(user.getRole());
UserEntity userEntity = userDealService.getUserEntity(user);
LogisticsUserDao and TruckOwnerDao both implement UserDealService interface.
If role is 4, driverDao return, if it is 5, truckOwnerDao return, but I have used
#Autowired
private DriverDao driverDao;
#Autowired
private TruckOwnerDao truckOwnerDao;
I don't want to use a map, like
put(4, driverDao);
because if I want to add other dao, I have to modify the code, it violates the open-closed.
So how can I solve the extend problem?
Thanks for all your help and suggestions in advance.

As it was already mentioned in comments, you need a factory, but there are few factories.
Factory - Creates objects without exposing the instantiation logic to the client and Refers to the newly created object through a common interface. Is a simplified version of Factory Method
Factory Method - Defines an interface for creating objects, but let subclasses to decide which class to instantiate and Refers to the newly created object through a common interface.
Abstract Factory - Offers the interface for creating a family of related objects, without explicitly specifying their classes.
I would consider factory method, that way Your "user" object would have method "user.createUserDealService()" which returns needed service.
Yet I'm not sure if this should be called service, services are objects that are remote callable.
By the way it looks strange for getting userEntity based on user. Isn't user an entity already?

Related

Saving entities in private methods

I have an Ingestion class that exposes a single method ingest. This method processes each section of a passed in form (section 1, section 2, etc, etc).
I have private methods for each section, saving the entity as it processes through. I'm aware that #Transactional has no effect on private methods, however I do not want to expose these methods but would like to use the functionality that #Transactional provides.
I'm looking to make sure each section completes in its own Transaction; I could do this through 'AspectJ' (as other SO answers have suggested) instead of Spring's out the box implementation, but I am trying to avoid due to the system wide changes it would cause.
Any thoughts on another approach?
The pseudo code provided below gives a general idea on the structure of the class:
public Class Ingestion {
// Autowired Repo's
...
...
#Transactional
public void ingest(Form form){
this.processSection1(form);
this.processSection2(form);
this.processSection3(form);
}
#Transactional
private void processSection1(Form form){
// do specific section 1 logic
section1Repo.save(form);
}
#Transactional
private void processSection2(Form form){
// do specific section2 logic
section2Repo.save(form);
}
#Transactional
private void processSection3(Form form){
// do specific section3 logic
section3Repo.save(form);
}
}
=========================================================================
This is not a duplicate question as marked in the comments. I know #Transactional doesnt work on private methods. My question is more along the lines of 'how do we get around this Spring AOP issue without having to use AspectJ'
The reason this doesn't work is that annotations like #Transactional add additional functionality that is intercepted by Spring's proxy object that wraps the actual object. But when you call a private method on an object with the this keyword, you're going straight to the real object and bypassing the proxy.
One way to solve this is to #Autowire the object into itself, and make the transactional calls via that autowired variable. You can still access private methods that way, and the call will be to a Spring-managed proxy instead of the bare object.
You may extract these three processing methods in another class, make them public, but set the class constructor access level to package-local (but not private, since Spring can't proxy classes with private constructors), so no classes from other packages could access these methods just because they are not able to instantiate their class. It doesn't hide these methods completely, but may fit your needs. This trick can be done with an inner class as well (note that it must be declared with package-local access).
To completely hide these methods, you may make use of declarative transaction management by injecting TransactionTemplate bean and using its execute method in private methods. This feature comes out-of-the-box. See more here.
Also, take note that for creating new transaction on executing method B from method A, method B must be declared #Transactional with propagation type REQUIRES_NEW. Otherwise, any nested methods will be invoked in the same transaction started by initial calling method.

Create an object of a java class whose constructor is annotated with #Autowired

There is a class whose constructor is annotated with #Autowired. I want to create an object of this class without actually passing the constructor parameters and using the default parameters. Can someone tell me how can i create an object of this class?
One of the reasons of using Spring framework is you don't create objects and manage them manually spring does it for you.If you can give some more details example code or something it will help to understand your situation better.
Spring is a dependency injection framework (it does hosts of other stuff as well). So the whole point is not to "create" your own instances and re-use the instances that Spring has created for you.
If you want create object of class whose constructor is marked as #Autowired then still you can create object of that class using normal new java operator.
You can create an object of that class by just marking your field with #Autowired.Spring handles object creation for you.

Spring MVC: #ManyToMany DAO?

In my application, i'm attemping to create a many-to-many relation with additional fields
following this tutorial:
hibernate-many-to-many-example-join-table-extra-column-annotation
I would like to know what the best practice says about where to put DAO methods related to this relationship.
is it better to create a dao specific for the association (ex. StockCategoryDAO) or put the methods in the StockDAO / Category ?
For example, I get confused thinking about that:
ex.1 - a method which gives me all Stocks associated to a category...
i don't need that because i already have getter in Category model class... right?
ex.2 - i will have a page under the Stock panel, where i will select (checkboxes) which categories
are associated to this stock (the stock already exists in db).
After submit, in the controller i get all selected checkboxes (if you know an examples how to this, you are welcome) and i have to call a service method (which encapsulates my dao) to insert
the association.
In this case is it better to use the setter of Stock class, followed by a session.update(stock) or use a StockCategoryService.addCategoryService(...) for each category selected?
thanks for any advices
I would think the basic design should be "Every Model class should have its own DAO class that has all the methods defined, that operate on that particular model". This includes all getters too.
DAO methods are based on model.
So, you need to put all the getter methods for the Stock in the StockDAO class.
And you can define the RowMapper class as a inner class in the DAO class, if you are using jdbctemplate and if you want to return custom objects
I would suggest you to use JdbcTemplate class. This minimizes the code in DAO class.
Here I have listed the steps to carry out this implementation:
Declare the JdbcTemplate bean in spring.xml and inject the datasource bean as property o jdbcTemplate bean
(So during initialization itself JdbcTemplate is created with right datasurce)
Implement DAO class for every model. Define all the methods (including getters) inside the DAO class.
if your getter method returns custom object, implement rowMapper class as inner class in the DAO class.
(implementing rowMapper gives jdbcTemplate, a sense about the resultset)

Configuring state of mocked object for different scenarios

I've a DAO and a service class. In the service class CapService, I've #Autowired a reference of DAO class CapDAO. The CapDAO class has a private instance field of type int, that has it's value injected from a properties file using #Value annotation.
class CapDAO {
#Value("${someProperty}")
private int expiryTime;
}
class CapService {
#Autowired
private CapDAO capDAO;
}
There is a method - retrieveCap() in the CapDAO class, which retrieves the caps from the database, based on the expiryTime. That method is invoked from another method in CapService class.
The CapService class uses the list returned from DAO method to create another object wrapping that list. And finally it returns that data structure.
Now, I'm testing a scenario using Mockito framework. I've two scenarios. In both of them, I want to invoke method of CapService class, which will get me the object. The list retrieved form database, will depend upon the value of expiryTime in the CapDAO class. And so will the content of the object returned by CapService class method.
In test, I'm invoking the method in Service class, and checking the value returned. Since DAO is reading expiryTime from properties file, both the test scenarios cannot pass with the same configured value. I've to have two differently configured DAO instance to be injected into Service class.
So, my question is - is there any way I can configure the expiryTime in CapDAO class, to create two different instance, or may be in a single instance only, and inject those in CapService based on scenario? No I don't have any setter for expiryTime. Yes, I knwo I can use reflection, but I would like to keep that as my last resort.
Short answer
reflection is easiest possibility, you can simply use ReflectionTestUtil. Note: If you have an interface which CapDAO implements, you need also AopUtils
Long answer
If you don't wanna use reflection, you need separate your context and test to get this work:
// context1.xml
<context:property-placeholder location="classpath:test1.properties"/>
// context2.xml
<context:property-placeholder location="classpath:test2.properties"/>
Then you can define someProperty with some other value in the properties.
personally i will recommend reflection.

Spring FactoryBean - Object Based On Values In Other Object

Getting right to it with a silly example:
Suppose I have created a FactoryBean implementation to create a Manager object.
public class ManagerFactory implements BeanFactory<Manager> {
// implemented methods from interface
}
Now, this factory needs to take a field called employeeId in order to look up an employee to prepopulate various fields of the Manager bean that the ManagerFactory creates (Yes, I know, in the real world Manager would extend Employee, lets pretend I can't do that).
So, since this employeeId field is not constant, is the only way to deal with this to create a setEmployeeId() method in the FactoryBean, then get the FactoryBean itself, then set the employeeId before calling getObject()?
Or am I making no sense whatsoever?
Jason

Categories