Inject the same class with different parameters with Guice [duplicate] - java

This question already has an answer here:
Guice: inject different implementation depending on who is getting it?
(1 answer)
Closed 5 years ago.
I have 2 different classes(Cart and Payment) trying to use same database accessor class DBAccessor, as DBAccessor only contains logic to read and write data from a DB in a fixed format.
public class Cart{
#Inject
Cart(#Cart DBService db){
}
..
}
public class Payment{
#Inject
Payment(#Payment DBService db){
}
..
}
public class CartDBService implements DBService{
#Inject
public CartDBService(DBAccessor){
}
}
public class PaymentDBService implements DBService{
#Inject
public PaymentDBService(DBAccessor){
}
}
public class DBAccessor{
#Inject
public DBAccessor(String tableName){
}
}
I want to inject dependencies using guice in the give setup making sure everything is created by guice.
I am using binding annotation to inject different DBService instances for Cart and Payment.
bind(DBService.class).annotatedWith(Cart.class).to(CartDBService.class);
bind(DBService.class).annotatedWith(Payment.class).to(PaymentDBService.class);
How do I inject separate DBAccessor classes for cart and order to make sure they get correct table names injected.

The issue is with the design: class DBAccessor is doing too much work since it's reading different kind of data from different tables, now Guice is saving you by showing you that you were a bad boy...
Solution: implement two DBAccessor-classes, if they have common logic you can extract it to default methods in an interface or to an abstract class and inherit from it. Then you'll ask Guice to provide different classes to the constructors.

You need to bind your DbAccessor class twice, with a different qualifier annotation for each table. Then your classes can each inject the right qualified binding they need.

Related

Use #Before in service for all methods in Java [duplicate]

This question already has answers here:
Lifecycle method of spring bean after bean is created
(2 answers)
Closed 2 months ago.
I am implementing a service for my controller in java. This service implements an interface with several methods, where each of them performs a different logic. However, they also have a common logic (they must call another #service).
I would like to know if there is any way to refactor this, that is, remove that common logic that they have to a method in the class of my service that is executed only once, at the beginning.
I'm looking for something similar to the following:
public class myClass implements myInterface{
private String stringToFill="";
#Before
public doSomeLogig(){
// call another service
stringToFill = "filled";
}
public getAll(){
...
//here I should use stringToFill, with value 'filled'
}
public getId(){
//here I should use stringToFill, with value 'filled'
...
}
public create(){
//here I should use stringToFill, with value 'filled'
...
}
}
There is a spring lifecycle annotation called as #PostConstruct, write a method in the class and add all the one time execution logic in this method and annotate it with the #PostConstruct annotation and spring would call this method automatically once the bean has been initialized.
Using AOP you can call a method in lots of different scenarios including the one you described.
Here is Link to Spring AOP documentation
Spring AOP
#Aspect
public class BeforeExample {
#Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doAccessCheck() {
// ...
}
}
You can Also define a custom annotation like #Before to do the magic for you.

Spring Data: multiple repository interfaces into a single 'repository' service class

I have quite some JpaRepository extended Repository interfaces due to the design of the database.
In order to construct a simple object i.e Person I have to make method calls to about 4 - 5 repositories just because the data is spread like that throughout the database. Something like this (pardon for pseudocode):
#Service
public class PersonConstructService {
public PersonConstructService(Repository repository,
RepositoryTwo repositoryTwo,
RepositoryThree repositoryThree) {
public Person constructPerson() {
person
.add(GetDataFromRepositoryOne())
.add(GetDataFromRepositoryTwo())
.add(GetDataFromRepositoryThree());
return person;
}
private SomeDataTypeReturnedOne GetDataFromRepositoryOne() {
repository.doSomething();
}
private SomeDataTypeReturnedTwo GetDataFromRepositoryTwo() {
repositoryTwo.doSomething();
}
private SomeDataTypeReturnedThree GetDataFromRepositoryThree() {
repositoryThree.doSomething();
}
}
}
PersonConstructService class uses all these interfaces just to construct a simple Person object. I am calling these repositories from different methods inside the PersonConstructService class. I have thought about spreading this class into multiple classes, but I do not think this is correct.
Instead I would like to use a repositoryService which would include all the repositories listed necessary for creation of a Person object. Is that a good approach? Is it possible in Spring?
The reason I am asking is that sometimes the count of injected Services into a class is about 7-8. This is definitely not good.
I do not think you can / shoudl create a meta-repository like abstraction. Repositories have a well defined meaning, conceptually, they are CRUD services (and a bit more sometimes :-)) for your Hibernate/JPA/Datastore entities. And I guess this is enough for them. Anything more is confusing.
Now what I would propose is a "smart" way of building your "Person" objects that is automa(g)tically aware of any new services that contribute to the meaning of the Person object.
The crux of it would be that :
you could have your Repositories implement a given Interface, say PersonDataProvider, which would have a method, say public PersonPart contributeDataToPersonBuidler(PersonBuilder).
You would make your #Service implement Spring's BeanFactoryPostProcessor interface, allowing you to inspect the container for all such PersonDataProvider instances, and inject them to your service (see accepted answer at How to collect and inject all beans of a given type in Spring XML configuration)
Your #Service implementation would then be to ask all the PersonDataProviders in turn to ask them to contribute their data.
I could expand a bit, but this seems to me like the way to go.
One could argue that this is not clean (it makes your Repositories aware of "something" that happens at the service layer, and they should not have to), and one could work around that, but it's simpler to expose the gist of the solution that way.
EDIT : since this post was first written, I came aware that Spring can auto-detect and inject all beans of a certain type, without the need of PostProcessors. See the accepted answer here : Autowire reference beans into list by type
I see it as a quite reasonable and practical data aggregation on Service layer.
It's perfectly achievable in Spring. If you have access to repositories code you can name them all like:
#Repository("repoOne")
public class RepositoryOne {
#Repository("repoTwo")
public class RepositoryTwo {
And inject them into the aggregation service as necessary:
#Service
public class MultipleRepoService {
#Autowired
#Qualifier("repoOne")
private RepositoryOne repositoryOne;
#Autowired
#Qualifier("repoTwo")
private RepositoryTwo repositoryTwo;
public void doMultipleBusiness() {
repositoryOne.one();
repositoryTwo.two();
}
}
In fact, you even don't need to name and Qualify them if they are different classes, but if they are in hierarchy or have the same interface...
Also, you can inject directly to constructing method if autowiring is not a case:
public void construct(#Qualifier("repoOne")RepositoryOne repoOne,
#Qualifier("repoTwo")RepositoryTwo repoTwo) {
repoOne.one();
repoTwo.two();
}

Autowiring in classes without RequestMapping

I am working on three different tables. I am using Hibernate to query these tables. I implemented successfully the DAO and the service layers, but i have few problems with the controller package. Here is my code, my controller package contains 3 classes , each should handle a table (i have 3 tables as i said before).
#Controller
public class Ods_Gis_Actel_Controller {
Param_Gis_Actel_Controller Param = new Param_Gis_Actel_Controller();
Tbl_Dim_Actel_Controller Dim = new Tbl_Dim_Actel_Controller();
#Autowired
Ods_Gis_Actel_metier service;
#RequestMapping(value="/index")
public String pageIndex(Model model)
{
addOdsTable(model);
Param.addParamTable(model);
Dim.addDimTable(model);
return "Affichage";
}
public void addOdsTable(Model model)
{
model.addAttribute("listeOds",service.getAll());
}
}
#Controller
public class Param_Gis_Actel_Controller {
#Autowired
Param_Gis_Actel_metier service;
public void addParamTable(Model model)
{
model.addAttribute("listeParam",service.getAll());
}
}
#Controller
public class Tbl_Dim_Actel_Controller {
#Autowired
Tbl_Dim_Actel_metier service;
public void addDimTable(Model model)
{
model.addAttribute("listeDim",service.getAll());
}
}
The request mapping is done in the 1st class, whose method calls 2 other methods from the other classes. But it seems, that the autowiring works only in the class, where the RequestMapping is performed.
Is this true?
how can i use the other methods from the classes which don't contain the RequestMapping if the autowiring doesn't work for them?
I gone through your problem , I think you are not so much aware the objective of #Controller , #RequestMapping . So First of all you need to know , why we use #Controller?, this is used to give business logic to your request. When request is hited from user , then your DispatcherServlet match the url from your request to value of RequestMapping annotation of all defined controller. And according to that , the matched mapping method is called and further procees done by framework. Now come to #Autowire, this is used to load the bean class definition from the xml configuration. So the #Autowire and #RequestMapping having different objective . So it's wrong to say here that the
**autowiring** works only in the class where the RequestMapping is performed.
Now your second question , How you can use simple class? there are two ways to achieve that as far as I know,
1) To create the Object of that class inside your class as you done in your code
2) To create the instance of that class using factory-method.
for the second point , you have to first define your class inside the configuration file by following the below format
<bean id="paramGis" class="<whatever_package_detail>.Param_Gis_Actel_Controller" factory-method="createInstance"/>
here one things you have to care that this method should be static .
and your class would look like that
#Service
public class Param_Gis_Actel_Controller {
private static Param_Gis_Actel_Controller paramGis;
public static Param_Gis_Actel_Controller createInstance(){
if(paramGis==null){
return new Param_Gis_Actel_Controller();
}
return paramGis;
}
public void addParamTable(Model model)
{
model.addAttribute("listeParam",service.getAll());
}
}
If you are still getting problem let me know.
I think you are having difficulties with the Java/Spring way. We don't use #Controller/#Autowired like that.
It's kind of hard to explain shortly (I strongly recommend you read the official document for that), but in short, you shouldn't create a Controller object inside another controller. The objects with annotation marks (#Controller, #Service...) should be generated and managed by Spring. At initiation time they will be injected with the #Autowired services by "Spring" way. Of courses you can intervene into that process, but by other special methods.
P/s: your naming convention is not for Java ;). If you create a program for personal use it maybe ok, but you will have difficult times collaborating with other Java developers.
Through method name as default one for access that particular method or use #Qualifier annotations.

Unit testing Spring 3 database methods

I have abstract class that defines database methods, such as inserts and updates, and a concrete class that implements it. The database configurations (dataSource, DatabaseTarget etc) are defined as beans in context.xml-file.
The database with its methods work in Controller when I'm using Spring 3 anotations by
private AbsractClass a;
Constructor:
#Autowired
public Controller(AbstractClass a) {
this.a =a;
}
...and a getter for a.
Calling database methods is done by
getA().insertValues();
But I would like to write Junit tests for my methods. Is there any example for this kind of situation? I have googled for hours.
If you want to test your controller methods without touching the database (which is the correct way), create a new class that extends the AbsractClass and pass it as argument to your Controller class, example:
CustomerController controller= new CustomerController(new InMemoryCustomerDao());
//call your actions and assert, all calls to the database will hit the InMemoryDao.
Another way is to use a Mock Object if you don't want to create extra fake classes in your project or you need to assert that these arguments are being correctly called.

Force Singleton Pattern on a Class implementing an Interface

I better explain the question with an example.
I have an Interface Model which can be used to access data.
There can be different implementations of Model which can represent the data in various format say XMl , txt format etc. Model is not concerned with the formats.
Lets say one such implementation is myxmlModel.
Now i want to force myxmlModel and every other implementation of Model to follow Singleton Pattern.The usual way is to make myxmlModels constructor private and provide a static factory method to return an instance of myModel class.But the problem is interface cannot have static method definitions and a result i cannot enforce a particular Factory method definition on all implementation of Model. So one implementation may end with providing getObject() and other may have getNewModel()..
One work around is to allow package access to myxmlModel's constructor and create a Factory class which creates the myxmlModel object and cache it for further use.
I was wondering if there is a better way to achieve the same functionality .
Make a factory that returns
instances of your interface, Model.
Make all concrete implementations of the model package-private classes
in the same package as your factory.
If your model is to be a singleton, and you are using java
5+, use enum instead of traditional
singleton, as it is safer.
public enum MyXMLModel{
INSTANCE();
//rest of class
};
EDIT:
Another possibility is to create delegate classes that do all the work and then use an enum to provide all of the Model Options.
for instance:
class MyXMLModelDelegate implements Model {
public void foo() { /*does foo*/}
...
}
class MyJSONModelDelegate implements Model {
public void foo() { /*does foo*/ }
...
}
public enum Models {
XML(new MyXMLModelDelgate()),
JSON(new MyJSONModelDelegate());
private Model delegate;
public Models(Model delegate) { this.delegate=delegate; }
public void foo() { delegate.foo(); }
}
You can use reflection. Something like this:
public interface Model {
class Singleton {
public static Model instance(Class<? extends Model> modelClass) {
try {
return (Model)modelClass.getField("instance").get(null);
} catch (blah-blah) {
blah-blah
}
}
}
public class XmlModel implements Model {
private static final Model instance = new XmlModel();
private XmlModel() {
}
}
usage:
Model.Singleton.instance(XmlModel.class)
Actually, I don't like this code much :). First, it uses reflection - very slow, second - there are possibilities of runtime errors in case of wrong definitions of classes.
Can you refactor the interface to be an abstract class? This will allow you to force a particular factory method down to all implementing classes.
I used to ask myself the same question. And I proposed the same answer ;-)
Now I normally drop the "forcing" behavior, I rely on documentation.
I found no case where the Singleton aspect was so compelling that it needed to be enforced by all means.
It is just a "best-practice" for the project.
I usually use Spring to instanciate such an object,
and it is the Spring configuration that makes it a Singleton.
Safe, and so easy ... plus additionnal Spring advantages (such as Proxying, substituing a different object once to make some tests etc...)
This is more an answer to your comment/clarification to kts's answer. Is it so, that the real problem is not using the Singleton pattern but instead defining an eclipse (equinox) extension point schema that allows contributing a singleton?
I think, this can't be done, because everytime you call IConfigurationElement.createExecutableExtension you create a new instance. This is quite incompatible with your singleton requirement. And therefore you need the public default constructor so that everybody can create instances.
Unless you can change the extension point definition so that plugins contribute a ModelFactory rather than a model, like
public interface ModelFactory {
public Model getModelInstance();
}
So the extension user will instantiate a ModelFactory and use it to obtain the singleton.
If I guessed wrong, leave a comment and I delete the answer ;)

Categories