Spring Beginner - No such field error - spring

I am new to spring. I am developing one sample project using spring. I am getting the following exception when I provide a value in Beans.xml. Please provide solution.
Beans.xml:
<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="helloWorld" class="com.dhr.spring.beans.HelloWorld">
<property name="message" value="d" />
</bean>
</beans>
HelloWorld.java:
public class HelloWorld {
private String message;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
}
MainApp:
public class MainApp {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}
Exception:
Caused by: java.lang.NoSuchFieldError: NULL
at org.springframework.expression.TypedValue.<clinit>(TypedValue.java:31)
at org.springframework.expression.spel.support.StandardEvaluationContext.setRootObject(StandardEvaluationContext.java:85)
at org.springframework.expression.spel.support.StandardEvaluationContext.<init>(StandardEvaluationContext.java:74)
at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:124)
at org.springframework.beans.factory.support.AbstractBeanFactory.evaluateBeanDefinitionString(AbstractBeanFactory.java:1299)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.evaluate(BeanDefinitionValueResolver.java:210)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:182)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
... 11 more

Welcome! To the ambiguous world of Spring! Where stack traces are long and documentation is short convoluted.
I have seen this error several times and, at least for me, it usually has to do with dependency inconsistencies.
I see that you just posted you are not using Maven. I can almost assure you that that is the problem. You really SHOULD be using Maven. The amount of work it will save you is monumental.
Edit: To make this post more answer-like: You are getting the error due to dependency inconsistencies. You are manually putting Spring JAR files into your dependency tree which is not recommended.
Either 1) Use Maven to handle dependency management (recommended) or 2) Ensure that all your JAR files utilize non-conflicting and coherent dependency trees.
For instance, you are using org.springframework.expression-3.0.3.RELEASE which is not part of the 3.1.x group. So, replace the jar file with org.springframework.expression-3.1.0-RELEASE

Related

Cannot find class for bean with name defined in class path resource [applicationContext.xml]

I'm posting my query after visiting numerous question posted before on same context, unfortunately none of them resolved my problem. I'm trying a complete xml based configuration in spring without using any annotation. But as soon as i launch the application, i'm getting the following exception.
Cannot find class [com.kashyap.springboot.xml.JdbcConnectionXML.java]
for bean with name 'connection' defined in class path resource
[applicationContext.xml]; nested exception is
java.lang.ClassNotFoundException:
com.kashyap.springboot.xml.JdbcConnectionXML.java
Things i've already taken care of :-
Namespace for component scan re-examined.
Tag for component scan entered.
Bean tag with proper classes' qualified name re-examined.
Bean property and references re-visited.
applicationContext.xml is located on path src/main/resources so no
absolute path required.
Context initialized with ClassPathXmlApplicationContext class.
Classes are already defined with default public constructors for instantiation required by reflection.(though it is not mandatory, used it as precaution). Alas!!! none of the these things worked. Please find the classes and xml below.
package com.kashyap.springboot.xml;
public class JdbcConnectionXML {
public JdbcConnectionXML(){
System.out.println("JDBC XML Constructor Called");
}
}
package com.kashyap.springboot.xml;
public class PrototypeXMLDAO {
public PrototypeXMLDAO(){
System.out.println("PrototypeXMLDAO Constructor Called");
}
private JdbcConnectionXML connection;
public JdbcConnectionXML getConnection() {
return connection;
}
public void setConnection(JdbcConnectionXML connection) {
this.connection = connection;
}
}
package com.kashyap.springboot.xml;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringbootdevApplication {
public static void main(String[] args) {
try (ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");) {
PrototypeXMLDAO pdCDIOne = context.getBean(PrototypeXMLDAO.class);
PrototypeXMLDAO pdCDITwo = context.getBean(PrototypeXMLDAO.class);
System.out.println(pdCDIOne);
System.out.println(pdCDIOne.getConnection());
System.out.println(pdCDITwo);
System.out.println(pdCDITwo.getConnection());
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.kashyap.springboot.xml" />
<bean id="connection" class="com.kashyap.springboot.xml.JdbcConnectionXML">
</bean>
<bean id="prototype" class="com.kashyap.springboot.xml.PrototypeXMLDAO">
<property name="connection" ref="connection"></property>
</bean>
</beans>
The stack-trace on console as follows:-
Exception in thread "main"
org.springframework.beans.factory.CannotLoadBeanClassException: Cannot
find class [com.kashyap.springboot.xml.JdbcConnectionXML.java] for
bean with name 'connection' defined in class path resource
[applicationContext.xml]; nested exception is
java.lang.ClassNotFoundException:
com.kashyap.springboot.xml.JdbcConnectionXML.java at
org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1380)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:670)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:637)
at
org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1489)
at
org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1007)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:739)
at
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868)
at
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
at
org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:144)
at
org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:85)
at
com.kashyap.springboot.xml.SpringbootdevApplication.main(SpringbootdevApplication.java:13)
Caused by: java.lang.ClassNotFoundException:
com.kashyap.springboot.xml.JdbcConnectionXML.java at
java.net.URLClassLoader.findClass(URLClassLoader.java:381) at
java.lang.ClassLoader.loadClass(ClassLoader.java:424) at
sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at
java.lang.ClassLoader.loadClass(ClassLoader.java:357) at
org.springframework.util.ClassUtils.forName(ClassUtils.java:255) at
org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:418)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1428)
at
org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1372)
... 10 more
If required i'll post the pom.xml too. Any sort of help will be highly appreciated.

Spring property place holder is not resolving in jaxws:client (cxf) address property

Environment:
Spring MVC : 4.1.7.RELEASE
CXF: 3.0.0
java: 1.8
web.xml --- loads appContext.xml (spring cofigs) & cxfContext.xml (configs for cxf)
spring-servlet.xml --- loading the spring mvc configs.
I'm using the below way to load the properties file.
#Configuration
#PropertySource(value = { "classpath:config.properties" })
public class Configuration {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Properties are getting resolved and no issues except in one case.
I'm using CXF for webservices and the address property is not getting resolved when "${addressVal}" is used. All other properties inside the xml are gettign loaded except for "jaxws:client".
<jaxws:client id="port"
serviceClass="com.service.Myclass"
address="${addressVal}" />
Where is the problem. What I'm doing wrong.
Problem with servlet context / application context loading ?
Please advice.
I am having the same problem. Sadly no solution found yet. However, for anyone finding this question, a workaround is using the JaxWsProxyFactoryBean.
Example:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schema/jaxws.xsd">
<bean id="client" class="demo.spring.service.HelloWorld" factory-bean="clientFactory" factory-method="create"/>
<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass" value="demo.spring.service.HelloWorld"/>
<property name="address" value="${some.property.value}"/>
</bean>
It is not as nice, becuase you have to inject the factory, call create() and cast, but at least it works.
#Autowired
#Qualifier("clientFactory")
private JaxWsProxyFactoryBean factory;
public void callService() {
HelloWorld helloWorld = (demo.spring.service.HelloWorld)factory.create();
}
You can also add the following to your spring config to create a specific bean, but that did not work for me. Trying to inject that bean failed, which is why I settled on the method described above.
<bean id="client" class="demo.spring.service.HelloWorld" factory-bean="clientFactory" factory-method="create"/>
See also http://cxf.apache.org/docs/writing-a-service-with-spring.html at the bottom of the page

Scan specific packages for Spring AOP

I'm trying to use AOP into an existing (big) Spring project. The thing is that I don't want Spring to create proxies for all the objects in the ApplicationContext, mainly for performance but also because there are final classes that I cannot modify.
I've tried to make Spring search only inside "com.foo.bar.*" by defining the following aspect:
com.baz.MyAspect
#Aspect
public class MyAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(MyAspect.class);
#Before("within(com.foo.bar.*) && " +
"execution(* com.foo.bar.MyController.handleRequest(..))")
public void getData() {
// Nothing yet
}
}
And I've added this lines to the configuration:
<?xml version="1.0" encoding="utf-8"?>
<beans ...>
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="myAspect" class="com.baz.MyAspect"/>
</beans>
But when I run the app, I get the following Exception:
Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.foobar.FinalController]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class com.foobar.FinalController
So it seems that Spring is scanning packages other than the ones defined in the within expression. I would like to know whether there is a way to specify the packages to be scanned or any other way to solve this problem.
yes you can define your point cut like this
the execution of any method defined in the bar package or a sub-package:
execution(* com.foo.bar...(..)) click here for detail

Groovy-Spring Integration Issue [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
We have developed an application using following technologies stack:
Struts 2.1
Springs 3.1
Groovy 1.8
Tomcat 6.0.26 - For deployment
Our requirement is to migrate a specific layer of application to Groovy. We have migrated that layer to groovy and application is working fine. After the migration groovy beans are initialized properly by spring container but we are not able to utilize the 'dynamic language' feature of Groovy. That is when we modify Groovy script, updated changes are not reflected back to application dynamically.
For reference I am attaching a method of groovy script (GroovyConnection.groovy):
#Component
class GroovyConnection implements EndPointManager, Serializable{
private static final long serialVersionUID = 1481681752777429674L;
private final static Logger log = Logger.getLogger(GroovyConnection.class);
private static final String DESTINATION_DIR = ARTIFACT_DIR_PATH.toString()+"/";
private static final String JIVE_USER = ""; //"jivescpt";
/**
* #param default
*/
public GroovyConnection() {
super();
jschInstance = new JSch();
}
public String executeCommands(Session session, String inputCommand, Device device) {
log.info("Entering executeCommand() device:" + inputCommand);
Channel channel = null;
PipedOutputStream commandIO = null;
InputStream sessionInput = null;
InputStream sessionOutput = null;
InputStream sessionError = null;
String commandResponse = null;
try {
channel = session.openChannel("shell");
commandIO = new PipedOutputStream();
sessionInput = new PipedInputStream(commandIO);
channel.setInputStream(sessionInput);
sessionOutput = channel.getInputStream();
sessionError = channel.getExtInputStream();
channel.connect();
return fireCommandsOnTerminal(session, commandIO, sessionOutput, sessionError, inputCommand, device);
}
catch (JSchException e) {
log.error(AutomationConstants.ERROR_MSG.toString(), e);
}
catch (IOException e) {
log.error(AutomationConstants.ERROR_MSG.toString(), e);
}
catch (InterruptedException e) {
log.error(AutomationConstants.ERROR_MSG.toString(), e);
}
finally {
boolean isClosed = GroovyConnectionHelper.closeAll(session, channel, commandIO, sessionInput, sessionOutput, sessionError);
if (!isClosed) {
return AutomationUtils.getPropertyValue("jive.vpn.error.msg");
}
}
log.info("Exiting executeCommand() device:" + inputCommand);
return commandResponse;
}
}
Groovy-context 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"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd">
<lang:defaults refresh-check-delay="2000"/>
<lang:groovy id="endPointManager"
script-source="classpath:GroovyConnection.groovy" refresh-check-delay="1000">
</lang:groovy>
</beans>
Even after given refresh-check-delay time for 1 second groovy beans are not behaving accordingly at runtime. I have to restart Tomcat to redeploy updated groovy changes.
Looks like application treating groovy beans as java beans.
Apart from this if I execute a groovy script without using Springs, it executes as expected. Modified groovy script changes are reflected back dynamically. Here is code for reference:
groovy-script:
package com
public class test1 {
def hello_world() {
println "Connectddded"
}
}
Main Class:
public static void main(String arg[]) {
try {
new GroovyShell().parse(newFile("test1.groovy")).invokeMethod("hello_world", null);
} catch (CompilationFailedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
According to my understanding either we are missing something in Spring-Groovy Integration configuration that allows us to refresh back the Groovy beans modification or Tomcat is not allowing us refresh back the updated groovy script.
If someone can provide any suggesting on this would be helpful. Thanks in advance.
Regards,
Divya Garg
Thanks all, who have spent their time to read my post. Issue is resolved.
Actually we were using #component and groovy-context.xml file simultaneously because of that we were facing this issue. I have removed annotation and put my groovy file in classpath. Now everything is working file as expected. Groovy beans are getting refresh properly. But I coluld not achieve the same using spring annotations.
Now I am facing another issue and I tried a lot for it. I have another groovy bean where I have my all static methods called (GroovyConnectionHelper.groovy). I am not able to call these static methods in GroovyConnection.script. When application executes applcation get hangs on the place where execution reaches to GroovyConnectionHelper static method.
To resolve the issue I had tried to inject GroovyConnectionHelper bean in GroovyConnection as follows(Which is not good approach):
groovy-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd">
<lang:defaults refresh-check-delay="1000"/>
<lang:groovy name="endPointManager" script-source="classpath:GroovyConnection.groovy">
<lang:property name="groovyConnectionHelper" ref="groovyConnectionHelper"/>
</lang:groovy>
<lang:groovy id="groovyConnectionHelper" script-source="classpath:GroovyConnectionHelper.groovy"/>
</beans>
And i put the setter for the same in GroovyConnection.groovy:
public void setGroovyConnectionHelper(GroovyConnectionHelper groovyConnectionHelper) {
System.out.println( "Setting ----------------------------------------- groovyConnectionHelper : " + groovyConnectionHelper );
if ( null != groovyConnectionHelper ){
System.out.println( "Object groovyConnectionHelper: ::: " + groovyConnectionHelper.dump() );
}
this.groovyConnectionHelper = groovyConnectionHelper;
}
But this is not working out. Facing this error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.scripting.groovy.GroovyScriptFactory#0': BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scriptedObject.org.springframework.scripting.groovy.GroovyScriptFactory#0': Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'groovyConnectionHelper' of bean class [GroovyConnection]: Bean property 'groovyConnectionHelper' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:452)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:848)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:790)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
... 71 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scriptedObject.org.springframework.scripting.groovy.GroovyScriptFactory#0': Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'groovyConnectionHelper' of bean class [GroovyConnection]: Bean property 'groovyConnectionHelper' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1396)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:313)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.aop.target.dynamic.BeanFactoryRefreshableTargetSource.obtainFreshBean(BeanFactoryRefreshableTargetSource.java:77)
at org.springframework.scripting.support.RefreshableScriptTargetSource.obtainFreshBean(RefreshableScriptTargetSource.java:79)
at org.springframework.aop.target.dynamic.BeanFactoryRefreshableTargetSource.freshTarget(BeanFactoryRefreshableTargetSource.java:66)
at org.springframework.aop.target.dynamic.AbstractRefreshableTargetSource.refresh(AbstractRefreshableTargetSource.java:97)
at org.springframework.aop.target.dynamic.AbstractRefreshableTargetSource.getTargetClass(AbstractRefreshableTargetSource.java:68)
at org.springframework.scripting.support.ScriptFactoryPostProcessor.createRefreshableProxy(ScriptFactoryPostProcessor.java:553)
at org.springframework.scripting.support.ScriptFactoryPostProcessor.postProcessBeforeInstantiation(ScriptFactoryPostProcessor.java:322)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:880)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:852)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:446)
... 79 more
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'groovyConnectionHelper' of bean class [GroovyConnection]: Bean property 'groovyConnectionHelper' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1064)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:924)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:76)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:58)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1393)
... 94 more
Please suggest should I use Groovy Bean Injection for this or we can directely call groovy static methods direcly. Thanks in advance
Regards,
Divya Garg

#ExceptionHandler not working with Spring MVC 3.1 unit test

I'm able to do nearly all of the unit test on my Spring MVC controller by instantiating the object outside of the normal servlet context. But I would like to be able to run some tests to insure that my object serialization is working properly, headers are being generated, etc.
To run a test inside the servlet context, I create a modified context file so that various beans are NOT constructed, then I create mocked versions of those beans in my test case using EasyMock. I then invoke my handler with code like this, and get most of what I need from the MockHttpServletResponse.
I think this gets the essence of it:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "file:root-context.xml",
"file:junit-servlet-context.xml" } )
public class HomeControllerConfigHandlerHttp {
#Autowired
private RequestMappingHandlerAdapter handlerAdapter;
#Autowired
private RequestMappingHandlerMapping handlerMapping;
... //miscellaneous setup
public void someTest() throws Exception
{
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
request.setRequestURI("/config");
request.addParameter("foo", "bar");
request.addParameter("device", "oakmont");
MockHttpServletResponse response = new MockHttpServletResponse();
Object handler = handlerMapping.getHandler(request).getHandler();
replay(dblient);
expect(serviceClient.checkDevice("oakmont")).andReturn( true );
serviceClient.destroy();
replay(serviceClient);
ModelAndView modelAndView = handlerAdapter.handle(request, response, handler);
String content = new String( response.getContentAsByteArray() );
Assert.assertEquals(content, "Expected configuration");
String content_type = response.getHeader("Content-type");
Assert.assertEquals( content_type, "text/plain");
int status = response.getStatus();
Assert.assertEquals(status, 200 );
This does what I expect it to do, but there is one catch. I do a lot of error handling in my controller with an #ExceptionHandler. It is an easy way to back out of an error case in any handler, and it gives me a consistent way of exposing errors.
The #ExceptionHandler works fine in normal servlet deployment, but in this unit test mockup it does not get invoked when I throw an exception. Stepping into the Spring code is a bit of a challenge for me, I'm new to it and so I get lost pretty quickly. However, it looks like in the normal servlet environment, there is an exception handler that looks for an annotated handler. When running under SpringJUnit4ClassRunner, the exception isn't processed the same way.
If there is a way to fix this, I'd like to do it. I've avoided spring-test-mvc because of a lack of pioneer spirit, but if someone tells me that it can manage this just fine, I'll try that instead.
The contents of my junit-servlet-context.xml file are nearly identical to the servlet-context.xml file created by the Spring Template MVC wizard. The only difference is the addition of an exclude-filter that is used to prevent instantiation of a #Component that creates a few singletons used by my controller.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.cisco.onplus.home.dmz" >
<context:exclude-filter type="regex" expression=".*InitDatabase.*"/>
</context:component-scan>
</beans:beans>
Add following class for loading Dispatcher servlet in context:
public class MockWebApplicationContext extends AbstractContextLoader {
#Override
public ApplicationContext loadContext(MergedContextConfiguration mergedContextConfiguration) throws Exception {
String[] locations = mergedContextConfiguration.getLocations();
return loadContext(locations);
}
#Override
public ApplicationContext loadContext(String... locations) throws Exception {
XmlWebApplicationContext webApplicationContext = new XmlWebApplicationContext();
webApplicationContext.setConfigLocations(locations);
webApplicationContext.setServletContext(new MockServletContext(new FileSystemResourceLoader() ) );
ServletConfig config = new MockServletConfig();
config.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, webApplicationContext);
final DispatcherServlet servlet = new DispatcherServlet(webApplicationContext);
webApplicationContext.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.registerResolvableDependency(DispatcherServlet.class, servlet);
}
});
webApplicationContext.refresh();
servlet.init(config);
return webApplicationContext;
}
#Override
protected String getResourceSuffix() {
return ".xml";
}
}
Once you are done with that use
#ContextConfiguration(locations = {"classpath:app-config.xml",loader = MockWebApplicationContext.class)
to load DispatcherServlet using Autowired annotation on test class. Process it using
servlet.service(request,response);
Now it should handle exception flow also.
It probably requires 3.1.2 though.
I am afraid you will have to look at spring-test-mvc, the reason is the handling of exception from the controllers and using ExceptionResolver to call the appropriate #ExceptionHandler is done at the level of DispatcherServlet, not HandlerAdapter. The test that you have starts at the level of HandlerAdapter.
I highly recommend spring-test-mvc though, I have been using it for a while and have not seen any issues for my scenarios - http://biju-allandsundry.blogspot.com/2012/07/spring-mvc-integration-tests.html.
A test for an exception flow would look like this with spring-test-mvc:
xmlConfigSetup("classpath:/META-INF/spring/web/webmvc-config.xml")
.configureWebAppRootDir("src/main/webapp", false).build()
.perform(get("/contexts/exception"))
.andExpect(status().isOk())
.andExpect(view().name("exceptionPage"));

Resources