I am injecting dependency in one class. But not finding when I call method of that class.
public StudentValidator extends MyValidator implements Validator{
private StudentRepository studentRepository;
//setter for the same
public void validate(Object obj,Errors errors){
validateStudent(Obj)
}
}
public class MyValidator{
private StudentRepository studentRep;
public void setStudentRep(StudentRepository studentRep){
System.out.println("This is printing on Tomcat console");
this.studentRep=studentRep
System.out.println("This is also printing"+studentRep+" with hashcode");
}
public void validateStudent(Object obj){
studentRep.findStud(); getting here NullPointerException
}
}
No need of writing Spring servlet as I can see dependency has been injected in setters through Syso statements.
What would be problem for the same?
UPDATE
spring-servlet.xml
<beans>
<bean id="studentValidator" class="SyudentValidator" >
<property name="studentRepository" ref="studentRepository">
</bean>
<bean id="myValidator" class="MyValidator">
<property name="studentRep" ref="studentRepository">
</bean>
<bean id="studentRepository" class="StudentRepository">
</beans>
NullPointerException is not my problem. Problem is why I am getting the null pointer in this case as Syso statement is printing my dependencies hashcode.
Assuming both MyValidator and StudentValidator are spring beans, you should try:
bean id="myValidator" class="MyValidator.java">
bean id="studentValidator" class="StudentValidator.java" parent="myValidator>
You must notify spring that there is an inheritance.
You have declared a field of type StudentRepository twice, which is confusing but here's what I think is going on.
I assume you are creating an instance of StudentValidator, which will set the field StudentValidator.studentRepository. However your validateStudent method uses the field MyValidator.studentRep that will remain null, hence the NullPointerException.
Basically, only methods can be overridden in Java, not fields.
If you really need this unnecessary inheritance structure, the code should read:
public class MyValidator
{
private StudentRepository studentRepository;
public void setStudentRepository(StudentRepository studentRepository)
{
this.studentRepository = studentRepository;
}
public void validateStudent(Object obj)
{
studentRepository.findStud();
}
}
public StudentValidator extends MyValidator implements Validator
{
#Override
public void validate(Object obj, Errors errors)
{
validateStudent(Obj)
}
}
Though I'd be tempted to simplify it to:
public class StudentValidator implements Validator
{
private StudentRepository studentRepository;
public void setStudentRepository(StudentRepository studentRepository)
{
this.studentRepository = studentRepository;
}
#Override
public void validate(Object obj)
{
studentRepository.findStud();
}
}
UPDATE
Based on the Spring configuration above, I can see you are creating instances of both classes - not sure why you'd do that if you're not going to use the myValidator bean as a parent of the studentValidator bean, but either way, if you've only got one bean, using a parent just complicates the Spring configuration of no reason.
The reason you're getting a NullPointerException in the validateStudent is because you never set the studentRep on the studentValidator bean, you only set it on the myValidator bean (they're two different instances).
Given this, you're Spring config should read:
<beans>
<bean id="studentValidator" class="SyudentValidator" >
<property name="studentRepository" ref="studentRepository">
<property name="studentRep" ref="studentRepository">
</bean>
<bean id="studentRepository" class="StudentRepository">
Though as I said, your class design is confusing in the first place, which makes this Spring config look weird as you're setting a reference to the same bean, studentRepository, twice.
My advice would be to apply the class changes I originally suggested, which simply the design as a whole and make it harder to misconfigure you application as is currently happening.
Related
I have an application that consists of 2 modules.
First of them is main one and it can work without second module installed.
I have beans with default implementation defined in beans.xml file of main module. And when installing second module I want to keep the ids of those beans but change the implementation to use new classes.
What is the best way to do that?
beans.xml of first module:
...
<bean id="myCoolService" class="com.blabla.defaultCoolServiceImpl">
...
and after the installation of second module I want to use the implementation of myCoolService that is defined in second module.
Upd:
Spring version is 3.2.4.
I need to make as little changes as possible so I need to continue using xml-driven configuration.
One way of doing this is introducing a common interface (I guess one should already be present):
public interface MyInterface {
//...
}
And then in the main module annotate the default implementation with #Service
#Service
public class DefaultImplementation implements MyInterface {
//...
}
Then, if one of your modules needs to override this implementation, use the #Primary-annotation:
#Service
#Primary
public class OverridingImplementation implements MyInterface {
//...
}
Then, the following code:
#Inject
private MyInterface myInterface;
will inject DefaultImplementation if OverridingImplementation is not scanned, and inject OverridingImplementation (without complaining about multiple beans) if it is scanned.
One way to achieve this is going through a proxy, that redirects to the proper implementation. The proxy would normally redirect to the default. It will redirect to module 2 if it is available.
To help the proxy figure out what is available, you may need to have
a member that always points to the default implementation using "name" property.
have a method to register a different bean as the alternate implementation.
For example
Inside MyProxy:
#Autowired
public void setDefaultWorker(Worker defaultWorker) {
this.defaultWorker = defaultWorker;
}
private Worker defaultWorker;
private Worker alternateWorker;
public void registerAlternateWorker(Worker alternateWorker) {
this.alternateWorker = alternateWorker;
}
//To use the worker
private Worker getWorker() {
return alternateWorker == null? defaultWorker : alternateWorker;
}
In Module 1, your default implementation bean should be declared as having the defaultWorker as name
<bean id="defaultWorker" class="MyDefaultWorkerImpl"/>
Module 2 can register itself to the proxy registry on startup using SmartLifeCycle.
if possible,use :
<bean id="myCoolService" class="${IMPL_CLASS_NAME}"/>
Define impl class in a property file.
IMPL_CLASS_NAME=com.blabla.SecondMduleCoolServiceImpl
OR other approach could be :
Lets say your defaultCoolServiceImpl and SecondMduleCoolServiceImpl implement ICoolService interface
You define these bean and an implementation of FactoryBean as below :
<bean id="mydefaultServiceimpl" class="com.blabla.defaultCoolServiceImpl">
<bean id="secondModuleCoolserviceimpl" class="com.blabla.SecondMduleCoolServiceImpl">
<bean id="myCoolService" class="com.blabla.ImplSelector"/>
public class ImplSelector implements FactoryBean<ICoolService>, ApplicationContextAware {
private ApplicationContext iApplicationContext;
// #Value("#{corePropertyConfigurer['defaultOrCool']}") you can injcet via property file.
private String defaultOrCool = "cool" ;
#Override
public ICoolService getObject() throws Exception {
if (StringUtils.equals(defaultOrCool, "default")) {
return iApplicationContext.getBean("mydefaultServiceimpl", ICoolService.class);
}
return iApplicationContext.getBean("secondModuleCoolserviceimpl", ICoolService.class);
}
#Override
public Class<?> getObjectType() {
return ICoolService.class;
}
#Override
public boolean isSingleton() {
return true;
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
iApplicationContext = applicationContext;
}
}
Then you can access myCoolService via autowiring or applicationContext.getBean("myCoolService", ICoolService.class);
In my jsp, I have a custom tag
<ex:SelfService />
which intrun calls the java class
public class SelfServiceClass extends SimpleTagSupport{
#Autowired
private ReloadablePropertyManagerImpl reloadableProperty;
public ReloadablePropertyManagerImpl getReloadableProperty() {
return reloadableProperty;
}
public void setReloadableProperty(
ReloadablePropertyManagerImpl reloadableProperty) {
this.reloadableProperty = reloadableProperty;
}
public void doTag() throws IOException {
JspWriter out = getJspContext().getOut();
out.println(getReloadableProperty().getPropertyValue("print.service"));
}
}
And in my spring.xml I have configured the bean,
<bean id="reloadableProperty" class="com.testing.portal.util.ReloadablePropertyManagerImpl" />
But I am getting null pointer exception when I call getPropertyValue() on reloadableProperty object.
Any help will be much appreciated.
Since your class is not managed by Spring you have to load the ReloadablePropertyManagerImpl from the application context by yourself. In order to do so you should create a class which implements ApplicationContextAware with a static getter for the context.
See more in this sample.
Is Spring aware of SelfServiceClass class? It has to be. You either annotate it with #Component or it is returned by a #Configuration as a #Bean or include it as you did with reloadebleProperty in the xml, i.e.: make it a spring managed bean
From this Q/A: How to define a List bean in Spring? I know I can define a List<Foo> fooList filled with Foo bean instances but using XML configuration. Here's an example:
public interface Foo {
//methods here...
void fooMethod();
}
#Service("foo")
#Scope("prototype")
public class FooImpl implements Foo {
//fields and methods...
#Override
public void fooMethod() {
//...
}
}
#Service("fooCache")
#Scope
public class FooCacheImpl implements Foo {
//fields and methods...
#Override
public void fooMethod() {
//retrieves data from some cache
//...
}
}
#Service("fooWS")
#Scope("prototype")
public class FooWSImpl implements Foo {
//fields and methods...
#Override
public void fooMethod() {
//retrieves data from web service
//...
}
}
I can configure a client through XML:
<bean id="fooClient" class="some.package.FooClient">
<property name="fooList">
<list>
<bean ... /> <!-- This may be fooImpl -->
<bean ... /> <!-- This may be fooCacheImpl -->
<bean ... /> <!-- This may be fooWSImpl -->
<!-- I can have more beans here -->
</list>
</property>
</bean>
I want to know if this can be done with annotations only, no need to define the bean through XML. Something like this:
#Component
#Scope("prototype")
public class FooClient {
//which annotation(s) to use here to fill this list with FooImpl instances?
//I understand that if I have two implementations of Foo I may use a #Qualifier
//or use another list to note the different implementations.
private List<Foo> fooList;
public void bar() {
for (Foo foo : fooList) {
foo.fooMethod();
}
}
}
I think it would be better a solution that doesn't involve injecting the ApplicationContext nor the BeanFactory so FooClient is not tightly coupled to Spring classes. Also, for my case, I cannot use any Java EE classes like javax.inject.Provider as shown in this blog post: Spring 2.5.x+3.0.x: Create prototype instances from code.
What about using a Factory Bean?
I know you mentioned you did not want to be too coupled to spring - with a factory bean your bean containing the list is not so coupled - just your factory is.
Something like
#Component("fooList")
class ListFactory<List<Foo>> implements FactoryBean, ApplicationContextAware {
ApplicationContext context;
public List<Foo>> getObject() {
List<Foo> list = new ArrayList();
list.add(context.getBean("foo");
list.add(context.getBean("foo");
return list;
}
public void setApplicationContext(ApplicationContext context) {
this.context = context;
}
public boolean isSingleton() {
return false;
}
}
#Component
#Scope("prototype")
class FooClient {
#Inject
#Named("footList")
private List<Foo> fooList;
public void bar() {
for (Foo foo : fooList) {
foo.fooMethod();
}
}
}
Haven't tried it myself, or had the scenario where I've needed it so I'm not sure it will work.
If you're doing it in the code directly, then I think using the PostConstruct annotation would be the way to go:
#Component
#Scope("prototype")
public class FooClient {
....
#PostConstruct
public void init() throws Exception {
fooList = new ArrayList<Foo>();
fooList.add(new FooImpl());
}
I think using this approach would be more flexible, since I think you will struggle with annotations only if the FooImpl objects themselves require additional configuration.
That's a limitation (or feature) of prototype scope. The docs say this
In contrast to the other scopes, Spring does not manage the complete
lifecycle of a prototype bean: the container instantiates, configures,
and otherwise assembles a prototype object, and hands it to the
client, with no further record of that prototype instance.
So after Spring hands it off to you, it doesn't keep any reference to it and therefore cannot autowire any of them into your fooList. If you did add #Autowired
#Autowired
private List<Foo> fooList;
it would just create a new FooImpl object and autowire that as the single element in your List.
If you're trying to keep a reference of all the Foo instances created, you'll most likely have to do it yourself.
You can use method injection as this:
public class PrototypeClient {
protected abstract PrototypeBean createPrototype();
private List<PrototypeBean> createPrototypeList() {
int listSize = calculateListSize();
List<Prototype> result = new ArrayList<Prototype(listSize);
for (int i = 0; i < listSize; i++) {
result.add(createPrototype());
}
return result;
}
private int calculateListSize() {
// do your stuff here
}
// ...
}
and have an Spring config as:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="prototypeBean"
class="fully.qualified.class.name.of.Prototype"
scope="prototype" />
<bean id="prototyeClient"
class="fully.qualified.class.name.of.PrototypeClient">
<lookup-method name="createPrototype" bean="prototypeBean"/>
</bean>
</beans>
No one so far was capable of providing a working correct example of interface injection in Spring Framework.
Martin Fowler article is not for mortals, everything else just words positioned in a very confusing way. I have surfed over THIRTY articles, where people either tell "Spring doesn't directly supports for interface injection"("and because I don't know exactly how I will only describe setter and constructor injections") or either "I will discuss it in my other threads" or either there will be few comments below saying that it is wrong example. I don't ask for explanation, I BEG for example.
There are three types of injection: Constructor, Setter and Interface. Spring doesn't support the latest directly(as I have observed people saying). So how is it done exactly?
Thank You,
According to Variants of DI in spring
DI exists in two major variants, Constructor-based dependency injection and Setter-based dependency injection.
Also see Interface injection is not implemented in Spring clearly states it.
So there are only two variants of DI. So if documentation says nothing about interface injection, its clear that its not there. Those who believe that interface injection is done by providing setter method in interface answer me:
Why spring ref doc left mention of interface injection?
Why can't interface injection via providing setter method NOT considered as setter injection itself. Why create special term for that when introduction of interface doesn't affect anything, I mean its still configured the same way. If they were different then how can one find it via seeing the config. Shouldn't it be transparent that in config and not seeing the impl that actually configured class implements some interface ?
Just like Instantiation using an instance factory method and Instantiation using an static factory method, some bean attributes should clarify the interface injection?
With interface injection an interface explicitly defines the point where a dependency can be set:
interface InjectPerson {
public void injectHere(Person p);
}
class Company implements InjectPerson {
Person injectedPerson;
public void injectHere(Person p) {
this.injectedPerson = p;
}
}
There are 3 types of dependency injections:-
1. Constructor Injection(E.g Pico Container, Spring supports it).
2. Setter Injection(E.g Spring supports it).
3. Interface Injection(E.g Avalon, Spring does not support it).
Spring supports only constructor and setter based injection.
Looks like you got confused in the different types(3) and what spring supports(2 of them).
Hi I tried with a very simple approach that may clarify your answer.
following is the code that i have built on using two interfaces and and two bean classes.
first interface with name Job.
public interface Job {
public void setmyJob(String myJob);
public String getmyJob();
}
and one class to implement this interface with name as MyJob
public class MyJob implements Job {
public String myJob;
public MyJob() {
System.out.println("From MyJob default Constructor and the ID= "+this);
}
public void setmyJob(String myJob) {
this.myJob=myJob;
}
public String getmyJob() {
return myJob;
}
}
In the next step i created another Interface with name as Service
public interface Service {
public void setJob(Job job);
public Job getJob();
}
and then again another class to implement this Service Interface.
public class MyService implements Service {
public Job job;
public void setJob(Job job) {
this.job=job;
System.out.println("Hello from Myservice: Job ID="+job);
}
public Job getJob() {
return job;
}
}
then i created on main class with the main function and written the code as follows:
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApplication {
public static void main(String...a) {
BeanFactory beanfactory=new ClassPathXmlApplicationContext("Beans.xml");
MyService myservice=(MyService)beanfactory.getBean("myservice");
System.out.println("Before print");
System.out.println(myservice.getJob().getmyJob());
}
}
in my Beans.xml file i mentioned the code as follows and it worked.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="myjob" class="MyJob">
<property name="myJob" value="My First String"/>
</bean>
<bean id="myservice" class="MyService">
<property name="job" ref="myjob"/>
</bean>
</beans>
I have also reffered to another online tutorials and then got this kind of solution. please let me know if you have any problem with this code. it is working for me.
I think, that the confusion around interface injection is caused by missunderstanding what the term "interface injection" actually means. In my understanding, interface injection describes the ability of a bean contener to inject a new interface to the bean, no matter that the class definition of this bean is not implementing it.
All examples presented here show how to create a bean out of concrete class, and then how to inject it into another bean. The fact, that in all cases bean is injected into a field defined as an interface does not matter- all operations are done with beans created out of concrete instances.
I can provide also another catchy example:
package creditCards;
interface PaymentCard {
Boolean isDebitAllowed();
}
<bean id="card" class="creditCards.PaymentCard">
<lookup-method name="isDebitAllowed" bean="boolValue"/>
</bean>
<bean id="boolValue" class="java.lang.Boolean">
<constructor-arg type="boolean" value="true"/>
</bean>
As you see here, it is even possible to create a bean out of interface! Still, it is not a interface injection, as IoC contener initializes instanse of this bean by its own. In other words, card bean is an initialized object, not an interface, what makes, that the selected answer for this question is correct.
I think someone answered your questions here
I also didn't know what Interface injection is until I read this statement from "Pro Spring MVC with web flow book"
"Note that interface-based dependency injection isn’t supported by the Spring Framework. This
means that we need to specify which concrete implementation to inject for a certain interface."
Please check the below example for iterface injection.
There is a shape interface and 2 concrete classes which imiplements shape namely square and rectangle.
The interface
package di.interfaceinjection;
public interface Shape {
public String shapeName();
public void displayName();
}
2 Implemented classes
package di.interfaceinjection;
public class Square implements Shape {
#Override
public String shapeName() {
return "Square";
}
#Override
public void displayName() {
System.out.println("Square");
}
}
package di.interfaceinjection;
public class Rectangle implements Shape{
#Override
public String shapeName() {
return "Rectangle";
}
#Override
public void displayName() {
System.out.println("Rectangle");
}
}
Now, we have a class which sets the shape.
public class ShapeSetter {
private Shape shape;
public Shape getShape() {
return shape;
}
public void setShape(Shape shape) {
this.shape = shape;
}
}
and finally the configuration
<bean id="shape1" class="di.interfaceinjection.ShapeSetter">
<property name="shape" ref="square"></property>
</bean>
<bean id="shape2" class="di.interfaceinjection.ShapeSetter">
<property name="shape" ref="rectangle"></property>
</bean>
<bean id="square" class="di.interfaceinjection.Square"></bean>
<bean id="rectangle" class="di.interfaceinjection.Rectangle"></bean>
Here,
we are injecting different shapes.
package di.interfaceinjection;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class InterfaceInjeection {
/**
* #param args
*/
public static void main(String[] args) {
ApplicationContext appContext = new ClassPathXmlApplicationContext("intro.xml");
ShapeSetter shape = (ShapeSetter)appContext.getBean("shape2");
shape.getShape().displayName();
}
}
I found similar question here Spring - how to inject a bean into class which is created many times at runtime? and Why is Spring's ApplicationContext.getBean considered bad? but neither really answers my case.
Example code:
public interface AppNameProvider
{
String getAppName();
}
public class DefaultAppNameProvider implements AppNameProvider
{
private String appName;
public String getAppName()
{
return appName;
}
public setAppName(String appName)
{
this.appName = appName;
}
}
<bean id="appNameProvider" class="some.package.DefaultAppNameProvider">
<property name="appName" value="MyApplication"/>
</bean>
public class MyException extends RuntimeException
{
// Imagine obligatory constructors here...
public String getAppName()
{
// Inject appNameProvider somehow here
return appNameProvider.getAppName();
}
}
I have a provider bean declared in xml. In the example the value is simply declared in xml for simplicity. I have a custom exception which needs to receive something from a bean. How to inject such bean into the exception class. I obviously can't declare exception as a Spring bean. The appName is just a simple example, it can be anything else. You might wonder why a hypothetic caller of myException.getAppName() wouldn't just simply call appNameProvider.getAppName()? Because it's not intended so, e.g. there might be different provider in each exception etc.
I would like to know how to inject the bean into such exception. I can add setter and set the provider at the exception throw time. But I have to know which provider to use from outside (in my app code) and I would have to do it redundantly everywhere where I want to throw this exception. Ideally I would like to declare which provider to use for the exception in the xml.
Ultimately the question can be widened so that instead of exception we think of any runtime object which is not a bean itself.
PS I'm not scared of having hardcoded dependencies to Spring in the code. I use Spring and I want to embrace it - not avoid it.
Inject the provider in the class which throws the exception
Provide a constructor/setter by which to set the provider to the exception
throw new MyException(provider)
It's a while since I've done it, but if you are using / can use annotation based config and aspectJ you can annotate a class as #Configurable which will allow you get Spring to inject dependencies each time an instance of the class is created.
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/aop.html#aop-atconfigurable
You can create a component and inject the property in it. For example you can define DefaultAppNameProvider as a component and thus you can autowire other components in it. You can then provide using a singleton design pattern with a private constructor a static method called getInstance. In the class MyException you can access the DefaultAppNameProvider property using DefaultAppNameProvider.getInstance().getAppName().
Example code for the singleton component.
#Component
public class DefaultAppNameProvider {
private static DefaultAppNameProvider instance;
private DefaultAppNameProvider() {
instance = this;
}
public static DefaultAppNameProvider getInstance() {
return instance;
}
private String appName;
public String getAppName()
{
return appName;
}
public setAppName(String appName)
{
this.appName = appName;
}
}
I have been looking around in the mean time. I found this. In the end I used the following solution.
According to 1 created an ApplicationContextProvider:
public class ApplicationContextProvider implements ApplicationContextAware
{
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext()
{
return applicationContext;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
ApplicationContextProvider.applicationContext = applicationContext;
}
}
Then AppNameProviderFactory which maps providers to the keys. Key can be exception name:
public class AppNameProviderFactory
{
private Map<String,AppNameProvider> map;
public void setMap(Map<String, AppNameProvider> map)
{
this.map = map;
}
public AppNameProvider getAppNameProvider(String key)
{
return map.get(key);
}
}
And in xml I define the mappings:
<bean id="appNameProviderFactory" class="some.domain.AppNameProviderFactory">
<property name="map">
<map>
<entry key="MyException" value-ref="appNameProvider"/>
</map>
</property>
</bean>
And finally in the exception class:
public class MyException extends RuntimeException
{
// Imagine obligatory constructors here...
public String getAppName()
{
final ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();
AppNameProviderFactory factory = (AppNameProviderFactory) applicationContext.getBean("appNameProviderFactory");
return factory.getAppNameProvider("MyException").getAppName();
}
}
This way I have configuration in xml, decoupled from business code. I can have as many exceptions with different providers as needed.
Thanks all for suggestions.
PS Error handling and NPE handling ommited for simplicity.