I got the following problem. I want to create SomeObject. This object consists of various nested objects NestedObject1, NestedObject2, ... I created mappers to create those nested objects Mapper1 to create NestedObject1, Mapper2 to create NestedObject2, and so on. Those Mappers call a huge amount of setters, and some of them need information from some entites from the db (and some don't). This is the problem in the java language:
public class MyClass {
#Inject
private MyDao dao;
#Inject
private Mapper1 mapper1;
#Inject
private Mapper2 mapper2;
#Inject
private Mapper3 mapper3;
#Inject
private Mapper4 mapper4;
#Inject
private Mapper5 mapper5;
public SomeObject map(Integer id) {
SomeEntity entity = dao.findById(id);
SomeObject someObject = new SomeObject();
someObject.setNestedObject1(mapper1.map(entity));
someObject.setNestedObject2(mapper2.map());
someObject.setNestedObject3(mapper3.map(entity));
someObject.setNestedObject4(mapper4.map(entity));
someObject.setNestedObject5(mapper5.map());
return someObject;
}
}
I am thinking of the following refactoring:
Make an interface Mapper and have all mappers implement this. Then I could inject the List of mappers. It would be pretty easy to add or remove on mapper, without touching MyClass. I think this is a good idea but the problem is the MyDao. Instead of one DB access I would then need 3.
The interface would then look like
public interface Mapper {
public void map(SomeObject someObject);
}
Mapper1 would look like
public class Mapper1 implements Mapper {
private static final Integer VALUTA = 1;
#Inject
private MyDao dao;
#Override
public void map(SomeObject someObject) {
SomeEntity entity = dao.findById(id); // and I have no idea what the id is
NestedObject1 nestedObject1 = new NestedObject1();
nestedObject1.setSomeField(entity.getSomething());
nestedObject1.setSomeOtherField(VALUTA);
someObject.setNestedObject1(nestedObject1);
}
}
id is unknown in this context. Include id in the signature? I have no idea...
Mapper3 and Mapper4 would have to look up the entity as well.
I was thinking about an abstract class which will look for the entity in the BeforeClass method, but I think this still get's called multiple times.
Btw: I know the title sucks, please feel free to rename it.
Related
I am attempting to implement dependency injection in a class that is inherited from a base abstract class, and I get the following error: "javax.enterprise.inject.spi.DeploymentException: It's not possible to automatically add a synthetic no-args constructor to an unproxyable bean class. You need to manually add a non-private no-args constructor to com...ExampleIntegrationProvider in order to fulfill the requirements for normal scoped/intercepted/decorated beans."
From what I researched, it seems that this happens because classes that are annotated with normal scoped beans such as #ApplicationScoped for example, need a non-private constructor without arguments, so that CDI can create a proxy of that class when it is injected in lazy mode. I was a bit surprised to find out, as I've never had problems with code like this:
#ApplicationScoped
public class UserService {
private final UserRepository userRepository;
#Inject
public UserUseCase(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User findById(long id) { ... }
}
Even though Quarkus magically adds a synthetic no-args constructor, how could it overcome the final field UserRepository? There would be a problem with its initialization as it needs to receive a value, I imagine it might end up being passed a null value..
Anyway, going straight to my case, here's an example of my current situation, with 3 important base classes and 1 implementation for a "Example" partner:
PartnerIntegration.java
#MappedSuperclass
public abstract class PartnerIntegration {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
// other common fields ...
}
PartnerIntegrationRepository.java
public interface PartnerIntegrationRepository<I extends PartnerIntegration> extends PanacheRepository<I> {
// common methods ...
}
PartnerIntegrationProvider.java
public abstract class PartnerIntegrationProvider<I extends PartnerIntegration> {
protected final PartnerIntegrationRepository<I> partnerIntegrationRepository;
protected PartnerIntegrationProvider(PartnerIntegrationRepository<I> partnerIntegrationRepository) {
this.partnerIntegrationRepository = partnerIntegrationRepository;
}
// code ...
}
And finally the final implementation ExampleIntegrationProvider.java:
#ApplicationScoped
public class ExampleIntegrationProvider extends PartnerIntegrationProvider<ExampleIntegration> {
#Inject
public ExampleIntegrationProvider(ExampleIntegrationRepository exampleIntegrationRepository) {
super(exampleIntegrationRepository);
}
// code ...
}
The abstract class PartnerIntegrationProvider is not annotated with any scope as I did not consider it necessary since it only receives the PartnerIntegrationRepository interface and not a concrete repository. But ExampleIntegrationProvider receives a concrete repository that is implementing that interface, so I annotated it with #ApplicationScoped to be able to inject the concrete repository with #Inject. But this generated that error.
I tried creating a public constructor method that passes the null parameter to the parent class, and the error disappeared, but this ends up polluting my code, since I do not want to allow that class to be instantiated without receiving a repository, so I removed the #ApplicationScoped and #Inject annotations from ExampleIntegrationProvider and created that class to produce the instance that will be injected from it:
ExampleIntegrationProviderBean.java
#Dependent
public class ExampleIntegrationProviderBean {
private static ExampleIntegrationProvider INSTANCE;
private final ExampleIntegrationRepository exampleIntegrationRepository;
#Inject
public ExampleIntegrationProviderBean(ExampleIntegrationRepository exampleIntegrationRepository) {
this.exampleIntegrationRepository = exampleIntegrationRepository;
}
#Produces
public ExampleIntegrationProvider exampleIntegrationProvider() {
return INSTANCE == null ?
(INSTANCE = new ExampleIntegrationProvider(exampleIntegrationRepository)) : INSTANCE;
}
}
But the number of partners may grow quickly, I wouldn't like to have to create other classes like this one to produce the instances, and even if it was just one partner, it doesn't seem like a very elegant solution...
Does anyone have any ideas on how I can resolve this in a better way?
I have an application class "Application", one abstract class "AbstractClass" extended by "Impl1" and "Impl2".
The application class gets the impl1 or impl2 to perform some task based on the input it receives.
Currently I am injecting both the classes into the application class as shown below.
Then based on input, I either ask impl1 OR impl2 to perform the task.
public class Application {
private static final Data data1 = DATA_CONFIG.data_1;
private final AbstractClass impl1;
private final AbstractClass impl2;
#Inject
Application(final AbstractClass impl1, final AbstractClass impl2){
this.impl1 = impl1;
this.impl2 = impl2;
}
public void mainTask(final Data data){
if(data == data1){
impl1.performTask();
}else{
impl2.performTask();
}
}
}
But, is there any way I could use assisted inject or a similar concept to inject only the dependency required, so for example input is data1, I only inject impl1 and not impl2.??
So, what you want is to select injected object depending to some context of injection point - value of Data object in particular. I didn't do such things and can't guarantee success, but you can try custom injections.
Also you can do something like factory. But IMHO, this approach is not much better than original, cause it will just move selection between impl1 and impl2 to a factory class you have to create first.
Sketch:
#Inject
Application(IAbstractClassFactory factory){
this.factory = factory
}
void mainTask(final Data data){
impl = factory.create(data)
}
Using static-method makes code more clean.
So I wanna use static-method even used with #Service, #Repository class in it.
You can more easily understand by code. Very short one and It works!!
But I want to know it is okay to use in any situation.
I didn't see like that code before, so I am afraid it is the effective code to use. If you have any idea about that, could you advise me, please?
#Repository
public class TruckRepository {
public Integer selectWheelCount() {
//which is searching truck database to get some data about trucks.
//Such as how many wheels does the truck have, something like that.
}
}
#Component
public class CarFactory {
private static TruckRepository truckRepository;
//#Autowired << can be omitted after spring 4.3 as I know
NewsSourceFactory(TruckRepository truckRepository) {
this.truckRepository = truckRepository;
}
public static Integer getWheelCount(String carType) {
swtich(carType) {
case TRUCK:
return truckRepository.selectWheelCount();
}
}
}
#Component
public class SomeCode {
public void something() {
Integer count = CarFactory.getWheelCount("TRUCK");
}
}
Add Comments
I very empressive the code of "Duration.class", "Stream.class" in java.
They are also using static-method, Of course they have no dynamic injection in there.
Just in case of thinking about the concise of code or clearness, isn't it the merit of static-method, dont you think? is it really harmless?
You are using static method which uses static field which is initialized in constructor. In this code it's not even clear when Spring will create a new instance of CarFactory (maybe it won't at all, if none is referencing it). And if no instance of CarFactory created, your static method is broken too, because static field is not initialized.
I don't see any benefits of using static methods in your case, after all you can always inject instance of CarFactory into SomeCode.
Simple as:
#Autowired
private CarFactory cartFactory;
Or better:
private CarFactory cartFactory;
public SomeCode(#Autowired CarFactory pCartFactory) {
cartFactory = pCartFactory;
}
I have a class which has a constructor where all the arguments are injected by GUICE.
Public class Order {
private final ClassOne classOneObj;
private final ClassTwo classTwoObj;
#Inject
public order(ClassOne classOneObj, ClassTwo classTwoObj){
this.classOneObj = classOneObj;
this.classTwoObj = classTwoObj;
}
}
Now, I want to add one more field(say, int status)variable which can't be injected.
Is it a good practice to create an object first with all the injected parameters and then set the new field which can't be injected with a setter method?
I came up with another approach where I created a factory class as given below:
public class OrderFactory {
private final ClassOne classOneObj;
private final ClassTwo classTwoObj;
#Inject
public order(ClassOne classOneObj, ClassTwo classTwoObj){
this.classOneObj = classOneObj;
this.classTwoObj = classTwoObj;
}
//getter methods for all the above variables
public ClassOne getclassOneObj(){
return classOneObj;
}
....
public Order createOrder(int status) {
return new Order(status, classOneObj, classTwoObj);
}
}
Then the new Order class will look like
public class Order {
int status
private final ClassOne classOneObj;
private final ClassTwo classTwoObj;
public order(int status, ClassOne classOneObj, ClassTwo classTwoObj){
this.status = status
this.classOneObj = classOneObj;
this.classTwoObj = classTwoObj;
}
//getter methods for all these member variables
}
Now to create the order object I will first create an OrderFactory object and then using the "createOrder" method I will create the Order object.
I am ending up with writing boilerplate code. Not sure if this is a good practice. Can anybody suggest on this if this approach is correct or there is any better approach for this problem?
I read in Google Guice and found there is a feature #Assisted for assisted injection for such cases. But I found that complex and couldn't convince myself whether I should go with that in my case.
Thanks in advance for any suggestion or guidance.
Your factory approach is excellent. Please don't use the setters: if the field can be made immutable, it should be immutable, whether or not it makes it "convenient" to instantiate.
Another approach you can take is Assisted Injection, which solves this exact problem. With that, you only define the factory interface, and its implementation is magically given to you by Guice:
class Order {
interface Factory {
Order create(Status status);
}
#AssistedInject Order(
ClassOne one,
ClassTwo two,
#Assisted Status status) {
}
}
Module code:
bind(Order.Factory.class).toProvider(
FactoryProvider.newFactory(Order.Factory.class, Order.class));
Then the clients inject Factory and use it just like they do in your example.
You're typically going to inject things that take some amount of effort to construct. If you're just injecting an int field, you'd be better off just calling a setter method on the object (that has some of it's more complex dependencies injected). Also, if a fields changes frequently, as implied by a field called "status", then it's also not a good candidate for injection.
I'm using datanucleus 3.2.5 / JDO for persisting objects to a MongoDB database.
While trying to persist one map of lists I'm getting the following exception:
RuntimeException: json can't serialize type [list element type here]
Some sample code:
#PersistenceCapable
public class SomeClass {
private Map<String, List<SomeOtherClass>> myAttribute;
// ...
}
#PersistenceCapable(embeddedOnly="true")
public class SomeOtherClass {
private String attribute;
// ...
}
I could get around this problem annotating the embedded attribute as #Serialized, but I would rather prefer a more elegant way.
Am I missing anything? Is there a better approach to this issue?
Quoting Andy's reply to my question in the DataNucleus forums:
No persistence spec defines any support for a container of a container. You are always recommended to make the inner container (List in your case) a field of an intermediate class.
So there are two approaches here:
Use an intermediate class
By far the most elegant and maintainable solution. Following the example toy code:
#PersistenceCapable
public class SomeClass {
private Map<String, SomeOtherClassContainer> myAttribute;
// ...
}
#PersistenceCapable(embeddedOnly="true")
public class SomeClassContainer {
private List<SomeOtherClass> myAttribute;
// ...
}
#PersistenceCapable(embeddedOnly="true")
public class SomeOtherClass {
private String attribute;
// ...
}
Mark the attribute as #Serializable
Ugly and probably a source of headaches, specially if relying on java default serialization.
#PersistenceCapable
public class SomeClass {
#Serializable
private Map<String, List<SomeOtherClass>> myAttribute;
// ...
}
#PersistenceCapable(embeddedOnly="true")
public class SomeOtherClass implements Serializable {
private String attribute;
// ...
}