I have an abstract class, which has many classes extending it. The abstract class has a field used by all the child classes. The field needs to be injected using guice.
public abstract class StrategyClass {
#Inject
ClassTobeInjected variableName;
}
I have a provider written for injecting this, which has a provider and a singleton:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
final AppConfigBinder appConfigBinder = new AppConfigBinder(binder());
appConfigBinder.bindPrefix("*");
}
#Provider
#Singleton
public ClassTobeInjected getfield() {
return new Instance of ClassTobeInjected;
}
}
I see that the provider is creating an instance. However the abstract class field is always null. Do I need to add anything in the configure of my module? Is there something I am missing?
Related
I had an issue to autowire an object in my abstract base class. It always give me null instead of an instance. Please help.
Base class:
public abstract class BaseClass implements IReq<Req> {
#Autowired
protected ReqDao dao;
protected void updateReq() {
dao.update();
}
}
Child class:
#Component
public class ChildClass extends BaseClass {
...
}
ReqDao class:
#Component
public class RptRequestDao {
public void update(){
...
}
}
I am thinking of simply use the update() function in Base class, which means in my ChildClass, I don't override that one. Is this the problem? If it is, what's the normal way to do it? Thanks in advance.
A bean is created on demand, in your case when you initialize your object,
RepoDao is private so it wont be inhereted to the class which will be intialized, you either need to put
#Component
public class ChildClass extends BaseClass {
#Autowired
private ReqDao dao;
or make it protected/public in BaseClass, sure public will make it accessible to other classes which violates the encapsulation
Instantiate your child class using #Autowired like this
public class SomeClass{
#Autowired
ChildClass childClass; //IMPORTANT
}
The error occurs when you try to instantiate the childClass like this:
public class SomeClass{
ChildClass childClass = new ChildClass();
}
BaseClass is abstract you can't instantiate it.You need to have your ReqDao in ChildClass to be autowired.Spring will only autowire when it will create an instance of that class.Hope that helps
Check how you are instantiating the child class. Make sure you are NOT using "new" keyword to instantiate child class.
ChildClass cc = new ChildClass() // **Not recommended**
You must autowire the childclass and let spring take care of bean creation.
I have a class that is annotated #Component that was then #Autowired into another class. However, I need to remove this #Component annotation and instead, create it with an #Bean annotated method in the class where its was previously autowired.
Where previously the classes looked like:
#Component
public class MyClass implements IMyClass
{
// Stuff
}
#Configuration
public class MyUsingClass
{
#Autowired
private IMyClass myClass;
private void methodUsingMyClass()
{
myClass.doStuff();
}
}
So now I have removed the #Component annotation and written a #Bean annotated method like this:
public class MyClass implements IMyClass
{
// Stuff
}
#Configuration
public class MyUsingClass
{
#Bean
public IMyClass getMyClass()
{
return new MyClass();
}
....
}
My question is around replacing the previous call of myClass.doStuff() to use the new bean. Do I now pass in a parameter of type MyClass to the private method:
private void methodUsingMyClass(final MyClass myClass)
{
myClass.doStuff();
}
... or do I call this method directly (doesn't seem the correct way to me):
private void methodUsingMyClass()
{
getMyClass().doStuff();
}
... or are neither of these correct?
I think you misunderstand the #Bean annotation. It can be used to create a Bean. So basically spring will scan all classes, will find your #Bean and create a Bean, not more. You can now use this bean, like if you would use one created with <bean></bean>. To actually use the bean you need to either get it from ApplicationContext or #Autowire it. Of course you can still use that function like any other function in your code, to create a new instance of that object, but that would contradict to what you want to achieve with beans
Using Annotations that solutions
public class MyClass implements IMyClass{
private OtherClassInjection otherClassInjection;
private OtherClassInjection2 otherClassInjection2;
MyClass(OtherClassInjection otherClassInjection, OtherClassInjection2 otherClassInjection2){
this.otherClassInjection=otherClassInjection;
this.otherClassInjection2=otherClassInjection2;
}
public void useObject(){
otherClassInjection.user();
}
}
#Bean(name = "myClass")
#Autowired
#Scope("prototype") //Define scope as needed
public MyClass getMyClass(#Qualifier("otherClassInjection") OtherClassInjection otherClassInjection,
OtherClassInjection2 otherClassInjection2) throws Exception
{
return new MyClass(otherClassInjection, otherClassInjection2);
}
that logical, it's work injection #Autowired when create a Bean if context are know that bean, that you will to want inject.
I'm use that way.
I want to refactor a method annotated with #PostContruct in a common class of all my controller.
public abstract class Controller {
#PostConstruct
protected void PostContruct() { ..}
}
public class AuthController extends Controller {}
public class CartController extends Controller {}
But spring doesn't seems to call my inherit method. What is the pattern to use in this situation ?
This works with Spring 4.2.0 and Spring Boot 1.2.5
public abstract class AbstractController {
#PostConstruct
protected void postConstruct() {
System.out.println("post construct");
}
}
#Controller
public class ConcreteController extends AbstractController {
}
It also works if you mark the method as abstract, keep the #PostConstruct in the parent and implement it in the child.
It does NOT work if #Controller is in the parent.
So I have a number of generics in Spring 3.2 and ideally my architecture would look something like this.
class GenericDao<T>{}
class GenericService<T, T_DAO extends GenericDao<T>>
{
// FAILS
#Autowired
T_DAO;
}
#Component
class Foo{}
#Repository
class FooDao extends GenericDao<Foo>{}
#Service
FooService extends GenericService<Foo, FooDao>{}
Unfortunately with multiple implementations of the generics the autowiring throws an error about multiple matching bean definitions. I assume this is because #Autowired processes before type erasure. Every solution I've found or come up with looks ugly to me or just inexplicably refuses to work. What is the best way around this problem?
How about adding a constructor to the GenericService and move the autowiring to the extending class, e.g.
class GenericService<T, T_DAO extends GenericDao<T>> {
private final T_DAO tDao;
GenericService(T_DAO tDao) {
this.tDao = tDao;
}
}
#Service
FooService extends GenericService<Foo, FooDao> {
#Autowired
FooService(FooDao fooDao) {
super(fooDao);
}
}
Update:
As of Spring 4.0 RC1, it is possible to autowire based on generic type, which means that you can write a generic service like
class GenericService<T, T_DAO extends GenericDao<T>> {
#Autowired
private T_DAO tDao;
}
and create multiple different Spring beans of it like:
#Service
class FooService extends GenericService<Foo, FooDao> {
}
Here is a closest solution. The specialized DAOs are annotated at the business layer. As in the question from OP, the best effort would be having an annotated DAO in the EntityDAO generic template itself. Type erasure seems to be not allowing the specialized type information to get passed onto the spring factories [resulting in reporting matching beans from all the specialized DAOs]
The Generic Entity DAO template
public class EntityDAO<T>
{
#Autowired
SessionFactory factory;
public Session getCurrentSession()
{
return factory.getCurrentSession();
}
public void create(T record)
{
getCurrentSession().save(record);
}
public void update(T record)
{
getCurrentSession().update(record);
}
public void delete(T record)
{
getCurrentSession().delete(record);
}
public void persist(T record)
{
getCurrentSession().saveOrUpdate(record);
}
public T get(Class<T> clazz, Integer id)
{
return (T) getCurrentSession().get(clazz, id);
}
}
The Generic Entity Based Business Layer Template
public abstract class EntityBusinessService<T>
implements Serializable
{
public abstract EntityDAO<T> getDAO();
//Rest of code.
}
An Example Specialized Entity DAO
#Transactional
#Repository
public class UserDAO
extends EntityDAO<User>
{
}
An Example Specialized Entity Business Class
#Transactional
#Service
#Scope("prototype")
public class UserBusinessService
extends EntityBusinessService<User>
{
#Autowired
UserDAO dao;
#Override
public EntityDAO<User> getDAO()
{
return dao;
}
//Rest of code
}
You can remove the #autowire annotation and perform delayed “autowire” using #PostConstruct and ServiceLocatorFactoryBean.
Your GenericService will look similar to this
public class GenericService<T, T_DAO extends GenericDao<T>>{
#Autowired
private DaoLocator daoLocatorFactoryBean;
//No need to autowried, autowireDao() will do this for you
T_DAO dao;
#SuppressWarnings("unchecked")
#PostConstruct
protected void autowireDao(){
//Read the actual class at run time
final Type type;
type = ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[1];
//figure out the class of the fully qualified class name
//this way you can know the bean name to look for
final String typeClass = type.toString();
String daoName = typeClass.substring(typeClass.lastIndexOf('.')+1
,typeClass.length());
daoName = Character.toLowerCase(daoName.charAt(0)) + daoName.substring(1);
this.dao = (T_DAO) daoLocatorFactoryBean.lookup(daoName);
}
daoLocatorFactoryBean does the magic for you.
In order to use it you need to add an interface similar to the one below:
public interface DaoLocator {
public GenericDao<?> lookup(String serviceName);
}
You need to add the following snippet to your applicationContext.xml
<bean id="daoLocatorFactoryBean"
class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
<property name="serviceLocatorInterface"
value="org.haim.springframwork.stackoverflow.DaoLocator" />
</bean>
This is a nice trick and it will save you little boilerplate classes.
B.T.W I do not see this boilerplate code as a big issue and the project I working for uses matsev approach.
Why do you want a generic service ? Service classes are meant for specific units of work involving multple entities. You can just inject a repository straight into a controller.
Here is an example of generic repository with constructor argument, you could also make each method Generic instead and have no constructor argument. But each method call would require class as parameter:
public class DomainRepository<T> {
#Resource(name = "sessionFactory")
protected SessionFactory sessionFactory;
public DomainRepository(Class genericType) {
this.genericType = genericType;
}
#Transactional(readOnly = true)
public T get(final long id) {
return (T) sessionFactory.getCurrentSession().get(genericType, id);
}
Example of bean definition for the generic repository - you could have multple different beans, using different contstructor args.
<bean id="tagRepository" class="com.yourcompnay.data.DomainRepository">
<constructor-arg value="com.yourcompnay.domain.Tag"/>
</bean>
Depdncy injection of bean using resource annotation
#Resource(name = "tagRepository")
private DomainRepository<Tag> tagRepository;
And this allows the Domainreposiroty to be subclassed for specific entities/methods, which woul dallow autowiring :
public class PersonRepository extends DomainRepository<Person> {
public PersonRepository(){
super(Person.class);
}
...
You should use autowiring in classes which extends these generics
For this question one needs to understand about what autowire is. In common terms we can say that through autowire we create a object instance/bean at the time of deployment of the web app. So now going with the question if you are declaring autowiring in multiple places with the same name. Then this error comes. Autowiring can be done in multiple ways so if you are using multiple type of autowiring technique, then also one could get this error.
Complete Generic Solution using Spring 4:
Domain Class
#Component
class Foo{
}
#Component
class Bar{
}
DAO Layer
interface GenericDao<T>{
//list of methods
}
class GenericDaoImpl<T> implements GenericDao<T>{
#Autowired
SessionFactory factory;
private Class<T> domainClass; // Get Class Type of <T>
public Session getCurrentSession(){
return factory.getCurrentSession();
}
public DaoImpl() {
this.domainClass = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), DaoImpl.class);
}
//implementation of methods
}
interface FooDao extends GenericDao<Foo>{
//Define extra methods if required
}
interface BarDao extends GenericDao<Bar>{
//Define extra methods if required
}
#Repository
class FooDao extends GenericDaoImpl<Foo> implements FooDao{
//implementation of extra methods
}
#Repository
class BarDao extends GenericDaoImpl<Bar> implements BarDao{
//implementation of extra methods
}
Service Layer
interface GenericService<T>{
//List of methods
}
class GenericServiceImpl<T> implements GenericService<T>{
#Autowire
protected GenericDao<T> dao; //used to access DAO layer
}
class FooService extends GenericService<Foo>{
//Add extra methods of required
}
class BarService extends GenericService<Bar>{
//Add extra methods of required
}
#Service
class FooServiceImpl extends GenericServiceImpl<Foo> implements GenericService<Foo>{
//implementation of extra methods
}
#Service
class BarServiceImpl extends GenericServiceImpl<Bar> implements GenericService<Bar>{
//implementation of extra methods
}
I got some propably trivial question.
If I got defined EJB3+ interface, lets say it's remote like that:
#Remote
public class FooServiceRemote {
void foo();
}
and one implementation
#Stateless
public class FooService implements FooServiceRemote {
void foo() { ... }
}
How does the application server by default resolves what implementation to use (and call via proxy) if he knows only #EJB annotation for dependency injection like on interface:
public class SomeClass {
#EJB
private FooServiceRemote fooService;
}
Is it done by reflection (shortening name of interface)? Or he scans possible implementations of such interface, choosing one. Or.. ? And what if I want to create more implementations of one interface, is it possible and how to specify what implementation should be instantiated (maybe it is possible via some argument of annotation).
Thanks:-)
In the rare case that you need to have two beans implementing the same interface (not a good practice), you can name them and choose which one you want by name.
#Stateless(name="FooService1")
public class FooService1 implements FooService { }
#Stateless(name="FooService2")
public class FooService2 implements FooService { }
public class SomeClass {
#EJB(beanName="FooService1")
private FooService fooService;
}
Other possible approaches are looking it up using JNDI or the mappedName property.
See the javadoc for EJB annotation here: http://download.oracle.com/javaee/6/api/javax/ejb/EJB.html
Just a fix,
#Remote
interface FooServiceRemote {
void foo();
}
#Stateless
public class FooService implements FooServiceRemote {
void foo() { ... }
}
With this, application server knows which classes implements the specified interface.
If you have two classes, you must specifify which class do you need.