I have a method in a controller:
public FormValidationResult submitFormAndSendEmail(#Valid ContactForm form, BindingResult result,
#HttpSessionParam(value = "lastTimeContactFormSent", required = false) Calendar lastTimeContactFormSent)
As you can see I have created a #HttpSessionParam annotation, this will take a variable from the HttpSession and put it into the specified method parameter.
However...
Before the argument is being resolved, I recieve an InstantiationExceptionConstructorAccessorImpl because calendar cannot be instantiated by a default constructor.
Using the given stacktrace, I see that the HandlerMethodInvoker within "resolveModelAttribute" is causing the instantiation.
How can i prevent this? I don't want an instantiation, I want to use my own WebArgumentResolver in order to fill the method parameter.
Any clues?
More info:
Stacktrace by Spring (3.0.4):
java.lang.InstantiationException
at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:126)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:104)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveModelAttribute(HandlerMethodInvoker.java:772)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:356)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:171)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:427)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:415)
I don't see the debugger hit the webargumentresolver.
The argument is defined in my application context (xml) as following:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="customArgumentResolver" ref="sessionParamResolver"/>
</bean>
<!-- annotation to resolve httpSession attributes -->
<bean id="sessionParamResolver" class="nl.usgpeople.vakgilde.spring.mvc.extensions.SessionParamArgumentResolver"/>
It looks like your argument resolver wasn't fired or didn't resolved the argument. Make sure that:
your resolver is correctly passed to AnnotationHandlerMethodAdapter
if your resolver is fired, it correctly resolves the argument
Looks like axtavt was right, partially. The WebArgument did not get resolved. However, it was defined in the context xml properly. So why did'nt it work?
The application-context.xml included an mvc-context.xml , (using the import tag). Within the mvc-context.xml I had defined the bean and such.
Moving the bean definition outside mvc-context.xml , above the import tag, made Spring 'notice' the bean and resolve in the appropriate order.
Looking further, it looks like as long as my sessionParamResolver bean is defined above the tag, it works. When placing my bean below this tag, it does not work.
Looking at the Spring documentation, at chapter 15.12 Configuring Spring MVC , it is said that it will define a AnnotationMethodHandlerAdapter. So I guess defining it beforehand makes sure it also uses your customArgumentResolvers.
Related
I'm trying to get a better understanding of the #Autowired annotations component scanning, but all the examples I found so far use context.getBean(..) at some point to get at least one Bean to start with.
I also read that doing that is considered bad practice , but I can't seem to find any information on how to do it without context.getBean(..)
Could somebody please enlighten me with an example and information on how to do this ?
Define your bean in xml and use
<context:component-scan base-package="com" />
<mvc:annotation-driven />
Bean def
<bean id="processEngine" class="com.processEngine">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
now you can get bean as following
#Autowired
private ProcessEngine processEngine;
how it works
spring scans the bean's recipes either from xml or java configuration. then spring creates a beanDefinitions which are 'loaded' into BeanFactory. BeanFactory triggers a set of BeanPostProcessors (BPP) which are scanning classes for particular annotations like Autowired/Resource/PostProcessor and etc. and do appropriate actions. in case when your class contains #Autowired annotation, AutowiredAnnotationBeanPostProcessor would auto wire required field (dependencies), and when creation of an object is done and all BPP worked out, object is ready to be used by the app, from this point your code can get 'ready' objects from container.
there are some cases when you would need to access this beans from the code which is out of spring's control and not managed by container. in order to do so, you would need to get the ApplicationContext (container) and call #getBean specifying either name or type. using applicationContext directly is not a good practice because there are some problems that you can come to, f.ex. id of a bean might be changed and if you refer to bean by id then NPE would be thrown.
configuration
there are several approaches to configure spring to scan the classes for finding bean recipes. one would be defining component-scan, in this case classes which are located in the path that you've set and having any of valid spring annotations like #Component, #Service, #Repository, #Controller (for web container) would be considered. another way would be specifying each bean separately using <bean> or #Bean.
examples.
if you want to create a web app then you should see DispatcherServlet with ContextLoaderListener classes. this classes would boot your app and load everything according to configuration. f.ex. here,
but if you want to create a desktop app, then you would end up with something like this
From time to time (usually when not using Spring Boot), I use something along the lines of the following code:
public static <T> T autowire(ApplicationContext ctx, T bean) {
ctx.getAutowireCapableBeanFactory().autowireBean(bean);
return bean;
}
In my main, I create an instance of the main application class that contains a few #Autowired annotations for the main services / entry points to my Spring application.
I'm new in spring Framework. And actually i was doing an experiment with spring actually.
Look at this HelloWorld.java:
public class HelloWorld {
private String messageee;
public void setMessage(String messageee){
this.messageee=messageee;
}
public void show(){
System.out.println("message: "+messageee);
}
}
You see in this program, I've one variable which is outside declared as private named as messageee and next variable which is parametrized with setter named as messageee. You see both have same name.
Okay.. Now look at this bean file:
<?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.xsd">
<bean id="helloWorld" class="com.springframework.HelloWorld">
<property name="message" value="Hello.. This is Spring Framework example."></property>
</bean>
</beans>
Here you see inside bean tag. I've declared the property name as message. I don't understand, when i give the name as messageee it gives an error as:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloWorld' defined in class path resource [beans.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'messageee' of bean class [com.springframework.HelloWorld]: Bean property 'messageee' is not writable or has an invalid setter method. Did you mean 'message'?
But when i give the name as message. It runs successfully. But i don't have any message's method or any kind of variables with this similar name. So, How setter works actually? Will you please elaborate?
Help would be appreciated!
You're confusing fields (or instance variables) with properties.
property is a term coming from the Java Beans specification. A property foo of a bean is data that can be accessed using a getter method called getFoo() (or isFoo() for a boolean) and/or set using a setter method called setFoo().
What these methods do internally, whether they get/set a variable or not, whether the variable is also named foo or anything else, is completely irrelevant. What matters is the name of the getter/setter.
So, when you define your bean and tell Spring to set the property named message, Spring will look for a method called setMessage(). It doesn't care about the private fields of your bean class.
The Spring IoC container also supports setter injection, which is the preferred method of dependency injection in Spring. Setter injection uses the set* methods in a class file to garner property names that are configurable in the spring XML config.
From a configuration standpoint, setter injection is easier to read because the property name being set is assigned as an attribute to the bean, along with the value being injected.
To determine the property names, Spring follows the JavaBeans Specification.
First of all, you are mixing up fields with properties - also your property name in the applicationContext.xml is wrong (it should be messageee)
You need to use #Autowired annotation with either:
1) fields i.e. messageee
or
2) setter i.e. setMessage()
If you are thinking "what is that!!???" Read about Spring's basic features with beans and how Spring is capable of taking POJOs (Plain Old Java Objects) to and configure them using the IoC framework. Read about #Autowired here - How does autowiring work in Spring?
Then you should be fine with this:
<bean id="helloWorld" class="com.springframework.HelloWorld">
<property name="message" value="Hello.. This is Spring Framework example."></property>
</bean>
BTW...good approach for looking into Spring by using the very basic Java stuff....good luck!
I wanted to know if I can pass a property to a bean I declared on a xml configuration file (for example on the applicationContext.xml):
<bean id="captchaVerifierFilter" class="org.abc.filter.CaptchaVerifierFilter"
p:useProxy="false"
p:proxyPort=""
p:proxyHost=""
p:failureUrl="/abc/main/loginfailed"
p:captchaCaptureFilter-ref="captchaCaptureFilter"
/>
I want to use the captchaVerifierFilter bean to test if a captcha is valid or not. Then I can set the failureUrl property to url "add-record" and redirect to that jsp.
How can I send a property (like failureUrl for example) through a controller. Is this possible? What should I code on the controller if it's possible?
Any idea? Thank you very much!
I think you should define both the success and the failure url as properties in your configuration and then let the filter decide which way to go.
You can change the properties of the bean if you make it accessible (by making it public or with a setter) but that is probably not want you want since it changes the property for the single bean instance in the application context which is used by several threads concurrently.
Best regards
Hacim
By default the beans in the context are in singleton scope. So when you set the value for the property failureUrl in one controller, another controller will also see this new value when it gets the bean from the context.
With Spring it is possible to inject a list of beans by the interface class like:
#Component
public class Service {
#Autowire
private List<InterfaceType> implementingBeans;
...
}
All defined beans that implement this interface will be present in this List.
The annotation based approach is not possible for me, as the Service class is in a module that must not have spring dependencies.
I need to use this mechanism from outside via xml configuration.
<bean id="service" class="...Service">
<property name="implementingBeans">
??? tell spring to create a list bean that resolves all beans of the interfaceType.
</property>
</bean>
Does anyone know how to solve this?
EDIT: Additionally, there are more than one spring applications that use this service. So the best solution would be to handle this szenario completely via xml configuration. I can then copy the xml parts to all spriong applications that need this.
I want to avoid having a kind of initializer bean that gets the service injected and must then be copied to all spring applications.
Kind regards.
An XML-only solution would simply have you declare a <bean> of the "external" type and provide an autowire value of "byType".
Controls whether bean properties are "autowired". This is an
automagical process in which bean references don't need to be coded
explicitly in the XML bean definition file, but rather the Spring
container works out dependencies.
[...]
"byType" Autowiring if there is exactly one bean of the property type in the container. If there is more than one, a fatal error is
raised, and you cannot use byType autowiring for that bean. If there
is none, nothing special happens.
The explanation is a little confusing in that we expect multiple InterfaceType beans, but the actual field is of type List and Spring will be able to dynamically instantiate one and add all the InterfaceType beans to it, then inject it.
Your XML would simply look like
<bean id="service" class="...Service" autowire="byType">
</bean>
My original suggested solution made use of SpEL.
In the module that does have Spring dependencies, create a DTO
#Component(value = "beanDTO")
public class BeanDTO {
#Autowire
private List<InterfaceType> implementingBeans;
public List<InterfaceType> getImplementingBeans() {
return implementingBeans;
}
}
and then use SpEL to retrieve the value of implementingBeans from the beanDTO bean.
<bean id="service" depends-on="beanDTO" class="...Service">
<property name="implementingBeans" value="{beanDTO.implementingBeans}" />
</bean>
Spring will create the BeanTDO bean, inject all the beans that are of type InterfaceType. It will then create the service bean and set its property from beanDTO's implementingBeans property.
Following comments on question:
In an effort to be more JSR 330 compliant, Spring has introduced support for Java EE's javax.inject package. You can now annotate your injection targets with #javax.inject.Inject instead of #Autowired. Similarly, you can use #Named instead of #Component. The documentation has more details.
I have a web controller which I configure in the controller-config.xml using
<mvc:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.ecommerce.web.controller" />
The controller has the #Controller annotation like below.
#Controller
public class HomeController
I have included the #Autowired annotation on the dependencies, but when I first start up the application I am unable to set any properties on the wired objects.
For example, I have a storeProfile object which when in debug mode I see has multiple properties set as it should.
But, when I try to set one of the storeProfile properties on an #Autowried bean it is still null or empty string!?
If you look at the attached images it shows that after I step past the line this.storeProfileContext.setStoreProfile(storeProf ile) the debugger still shows the storeProfile property as null
Actually, there are a couple dependencies which look like they are created (they are not null and the application functions), but I am unable to set anything on these objects.
I asked the same question on the Spring forums too - hoping to get this figured out.
Thanks so much!
That is because you are looking at the fields of the proxy, which gets created when you have <aop:scoped-proxy/>, if you invoke your getter for the set values, you should see the correct values retrieved from the proxied object.
The instances you are examining are CGLIB proxies.
CGLIB subclasses your beans, delegating all method invocations to the target beans.
So the fields of the super classes are still present but not used.