Spring autowiring in dozer's destination class - java

So, I was banging my head against the monitor for the last 4 hours and can't figure it out.
I am using Dozer for mapping and it works fine. However, I need one of my DAOs in the destination class and autowiring returns null. Here is a snippet of the class:
#Component
public class Address
{
#XmlElement(name = "street", required = true)
protected String street;
#XmlElement(name = "city", required = true)
protected String city;
#XmlElement(name = "zip", required = true)
protected zip;
#Autowired
private CityDao cityDao;
// Getters/setters
}
the cityDao is always null. I am fairly new to both Spring and Dozer, but the Dozer docs say that the destination classes are created with default constructors and as far as I understand the Spring should not have any problems with it. The cityDao is null though. Please help!

As has been mentioned in the comments, you should not be injecting a DAO into a DTO!
However if you absolutely need to do that for some reason, check out Spring's #Configurable support. Here is the Javadoc and also some more information here and here.
If setup correctly, it allows objects that are not explicitly managed by Spring, to benefit from features like auto-wiring dependencies.
In you example code, Address although being annotated with #Component, is not managed by Spring since it's being created using Dozer. That's why you would need #Configurable to inject CityDao into Address

Related

How to autowire a transient attribute?

I have an Entity for example Employee that contains a #Transient Object Salary which will be derived from a related table/Entity DailyTimeRecord (DTR). DTR object data retrieval uses Joins and it is also autowired in the Employee object. The list of DTR objects will be the basis in computing the value of the Salary Object.
I found here [1]: Why is my Spring #Autowired field null? that using new keyword should be avoided, and let IoC Container create objects. In addition, I want to avoid using new keyword to minimize the coupling of my codes and ensure future compatibility and support scalability as much as possible. Therefore, I have interface Salary and implemented by a SalaryImpl class.
But Each time I tried to run the codes the autowired on a transient attribute Salary, it is always null. And I found the root cause here [2]: How to populate #Transient field in JPA? that Transient will always be null in JPA.
How will I ever create a object that avoiding the use of new keyword while it is a transient attribute?
Entity Class
#Entity
Class Employee implements Serializable {
//Attributes from DB here
#OneToMany
#JoinColumn(name="empNumber", referencedColumnName = "empNumber")
private List<DTR> dtr;
#Autowired
#Transient
private Salary salary;
//getters ang setters here
public double computeSalary(){
}
}
Interface of Salary
public interface Salary {
public double computeSalary(List<Benefit> benefits, List<Deduction> deductions);
}
Base/Implementation class of interface salary
#Service
public class SalaryImpl implements Salary, Serializable {
//other attributes here
//getter and setters
//other methods
#Override
public double computeSalary(List<Benefit> benefits, List<Deduction> deductions){
return 0;
}
}
First, #Transient is from JPA which is nothing to do with Spring .
Second, to be able to let Spring to inject beans into Employee, Employee is also required to be registered as a spring bean. But in realty, you can think that Employee is created using "new" by JPA implementation behind scene. That 's why spring cannot auto wire other beans to it.
If you really need do it, you can use AspectJ to do it as described by the docs.
I personally did not try this approach as you can simply make your SalaryService to accept an Employee as one of its argument to compute his salary, which is much simpler and easy to understand than the AspectJ approach.
public interface SalaryService {
public double computeSalary(Employee employee , List<Benefit> benefits, List<Deduction> deductions);
}
And the client code looks like:
#Service
public class EmployeeService {
#Autowired
private SalaryService salaryService;
#Transactional
public void computeEmployeeSalary(Integer employeeId){
Employee employee = entityManager.find(Employee.class , employeeId);
salaryService.computeSalary(employee, .... ,.....);
}
}
Entity objects are created by JPA implementation (like Hibernate) and not managed by spring.
They're neither Singletons nor Prototypes, so generally speaking, you cannot use Autowiring on properties of entity beans (because Autowiring is something that only can be done on spring beans).
You might be interested to read This SO thread for ideas for some workarounds.

How to get rid of JpaRepository interfaces in Spring Boot

How do I avoid having a class and an interface per entity when using JPA with Spring Boot?
I have the following entity (and 10 other):
#Entity
#Table(name = "account")
public class Account {
#Id
#GeneratedValue
private Long id;
#Column(name = "username", nullable = false, unique = true)
private String username;
#Column(name = "password", nullable = false)
private String password;
...
In order to be able to persist this entity, I need to setup an interface per entity:
#Repository
public interface AccountRepository extends JpaRepository<Account, Long> {
}
and then #autowire it:
#Controller
public class AdminController {
#Autowired
AccountRepository accountRepo;
Account account = new Account();
account.setUsername(...);
...
accountRepo.save(account);
If I now have 10 entities, it means that I need to define 10 #Repository interfaces and #autowire each of those 10 interfaces.
How would I embed that save method directly into Account so that I only have to call account.save() and how do I get rid of all those #repository interfaces I have to declare per entity?
Most likely not the answer you like, but I give it to you anyways.
All this interfaces per class seems useless and boilerplate when starting a project, but this changes over time when a project gets larger. There are more and more custom database interactions per entity. Additionally you can also define queries for a group of entities by subclassing the JpaRepository class.
But it is possible to improve the controller sections of your code by declaring a base class handling the repository autowire.
Example how this could be done (requires I think Spring 4)
public class BaseController<Model> {
#Autowired
protected JpaRepository<Model, Long> repository;
}
#Controller
public class AdminController extends BaseController<Admin> {
}
One option, if your entities have some kind of relationship is to use #OneToMany, #OneToOne and friends type annotations. This won't effectively replace all repository interfaces, but might reduce the amount you need. Barring that, you could try the active record pattern. Spring has Spring Roo that has some code generators for this, but I'm admittedly not a big fan of Roo. A quick Google search turned up ActiveJPA which uses the active record style and gives you the benefits you're looking for without the need for Spring Roo, just doesn't look like it's been maintained in a while. https://github.com/ActiveJpa/activejpa

How to impose common constraint on class with javax.validation library?

I am using Bean Validation constraints to validate class instances at run time. I have many DTOs where each has multiple fields often with a common constraint. I want to add a constraint to the class so that it applies to all the properties of the class. (As lombok #NotNull constraint).
e.g
class Person {
#NotNull
private String name;
#NotNull
private String address;
#NotNULL
private String contact;
}
I want to make it something like this.
#NotNull
class Person {
private String name;
private String address;
private String contact
}
You cannot do this with plain Bean Validation. So just adding #NotNull to the class won't work.
One potential approach could be to utilize XML configuration. The idea would be to have your own annotation MyNotNull. Your framework would need to scan for these annotations and build the programmatic configuration for the class in question. This could for example be done via a annotation processor during compile time. Once you have the constraint mapping XML files add them to your jar and reference them in validation.xml. That's just a basic idea. Personally, I am not sure whether it is worth the effort.

How to make a property injection via #Value annotation mandatory?

I have the following Test.java POJO class being populated from a property file using the #ConfigurationProperties annotation. I have seen the usage of #Required annotation to make it a mandatory.
Rather than defining annotations at the setter method level, are there any annotations or options within the #Value annotation that I can use for defining conditions like Mandatory, NotNull, etc?
#Component
#ConfigurationProperties(prefix = "com.test")
public class Test {
private String name;
#Required
public void setName(String name) {
name = name;
}
public String getName(String name) {
name = name;
}
}
Is this the right and only way for making a particular attribute mandatory? What are the other such annotations I could use for such conditions or validations purpose?
You can use validation for the properties, just not in the way you envisaged.
What you can do is use standard validation annotations (like #NotNull etc.) on the fields (or setters) themselves.
For example
#NotNull
#Size(min=2, max=10)
private String name;
Check out this part of the documentation
What the documentation essentially says, is that you simply have to have a compatible JSR303 validator implementation on the classpath, and use the relevant annotations.
Spring Boot will take care of the rest
According to the Spring docs (currently 4.1.6.RELEASE), the Value annotation only has a single property, value, containing the value of the property. You can put a Spring EL expression in this, but that won't let you explicitly express notions like non-nullity.
Further, in your code snippet you're using #ConfigurationProperties which is an alternative approach to configuring property values, compared to the #Value annotation.
The way you're doing it, your Java getter/setter names need to map to the property names, i.e. prefix "com.test" + getName() / setName() matches property com.test.name=...
So, you don't need the #Value annotation to tell Spring what property to use.
With the #Value approach, your getters/setters don't have to match the property names, but you do have to annotate each property e.g. #Value("${com.test.name}") and on the class, a #PropertySource annotation pointing to the properties file that contains com.test.name=...
I found a couple of blog posts with code examples that use the 2 different ways to inject the same properties: http://blog.codeleak.pl/2014/09/using-configurationproperties-in-spring.html and http://blog.codeleak.pl/2014/09/testing-mail-code-in-spring-boot.html

MongoDb not saving Java POJO part of a spring application

I have the following Java Pojo part of an application I am making:
#Document
public class Resume implements ResumePlan,Serializable {
private static final long serialVersionUID = -5332235643191283709L;
#Id
private String id;
#Autowired(required=false)
private Objective objective;
#Autowired
private PersonalDetails personalDetails;
#Autowired
private Skills skills;
#Autowired(required=false)
private Experience experience;
#Autowired
private Education education;
#Autowired(required=false)
private References references;
#Autowired(required=false)
private Publications publications;
}
I am saving it by the following code:
mongoOperations.insert(resume);
When I check on the backend in the mongodb console:
following is getting stored:
db.resume.find();
{ "_id" : "test#abc.com+919876543210", "_class" : "com.springmyresume.resume.Resume" }
It is not storing the rest of the bean objects like PersonalDetails etc..
Can someone tell me what I am doing wrong here.
It is solved. I made the following changes.
1) Removed #Autowired annotation
2) Added #DBRef annotation
With the #Autowired annotation the field objects were not getting saved.
I don't know why this is the behaviour.
First please make sure that you have all necessary fields' classes (Objective, PersonalDetails) annotated as #Document.
For second, please provide getters and setters for fields objects.
Also please make sure, that you have specified actual #Id, otherwise spring will do it for you.
BTW, if you would like to not use embedding, you may use #DBRef annotation. Here is quite good information:
http://maciejwalkowiak.pl/blog/2012/04/30/spring-data-mongodb-cascade-save-on-dbref-objects/

Categories