Understand initialization time behaviour of mvc:annotation-driven - spring

I am trying to debug an issue with RequestMappingHandlerAdapter initialization and I have come to a conclusion by searching the Web that it is getting initialized from mvc:annotation-driven xml entry. Can anyone explain me briefly, how this initialization works i.e. what happens when the parser parses mvc:annotation-driven? Or point me to the code that does it and I will trace it through.
Some more context on this:
I was trying to get RequestMappingHandlerAdapter from the context via autowire but could not. It gave me:
No matching bean of type [org.springframework.web.servlet.mvc.method.annotation.RequestMappingH
andlerAdapter]
expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
Found this thread, but the solution does not does not work: Spring, Jackson and Customization (e.g. CustomDeserializer)
I am using: Spring 3.1.3
This is what my servlet xml file looks like ...
<context:annotation-config />
<context:component-scan base-package="com.xyz" />
<mvc:annotation-driven />
Thanks,
Parth

I would think it would cause either the AnnotationConfigApplicationContext or AnnotationConfigWebApplicationContext to search for the annotated classes and create/graph them. One way to figure things out would be to make a bean that throws a RuntimeException in its default constructor and see what the stack trace looks like.

Related

Spring ConflictingBeanDefinitionException

I have ProjectA defining a MyService class.
ProjectA contains multiple concrete services, for example: SomeService.
Now I have ProjectB, which is a spring boot project, having ProjectA as dependency.
ProjectB may add some functions to SomeService by defining its own public class SomeService extends project.a.SomeService {...}. The beans are scanned via #ImportResource("applicationContext.xml").
applicationContext.xml:
<beans ...>
<context:component-scan base-package="project">
<context:include-filter type="assignable"
expression="project.a.MyService" />
</context:component-scan>
</beans>
Main problem is: This leads to ConflictingBeanDefinitionException:
Annotation-specified bean name 'someService' for bean class
[project.a.SomeService] conflicts with existing,
non-compatible bean definition of same name and class [project.b.SomeService]
Although the exception is really clear, I have no idea how to solve it. After my research I'm relativley sure setAllowBeanDefinitionOverriding(true) should solve my problem. Maybe I just do it at the wrong time, but it never helped (also I think true is the default value).
My attempt:
I tried to avoid all scanning and register my beans by myself as well:
GenericApplicationContext ctx = (GenericApplicationContext) SpringApplication.run(ProjectBApplication.class, args);
ctx.getBeanFactory().registerSingleton("someService", new project.b.SomeService());
...
I can filter MyServices specifically this way but now I'm running in autowiring problems using SomeService in other (following!) beans.
Maybe I'm just registering the someService bean wrong?
I've already read about BeanPostProcessors, but I did not get how they could help me and where to use them correctly.
Keep in mind: any solution will fit, no matter if filtering MyService's in code, in xml, just tell spring to overwrite beans with more specific ones or what ever.
I figured out I just registered the bean wrong. Using
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(service);
context.registerBeanDefinition(beanName, beanDefinition);
solved the autowireing problem and at the moment every thing works fine.

Autowire Spring XML bean inside Spring JavaConfig

I have a xml bean definition and JavaConfig bean definition in the same project. The JavaConfig need to reference the XML bean. But When i autowire the xml bean definition inside JavaConfig I get NoSuchBean definition error. My question is: Isnt the xml beans and JavaConfig beans visible to each other? If not how do i inject the xml bean into JavaConfig? Thanks
Edit:
Changing #Autowire to #Resource fixed it, but i dont understand why. Autowire should go after type and the XML bean is of the type Autowire is annoted with.
If your bean is not being picked up by Autowire, you need to ensure the configuration file for the beans is being read and in turn is generating the beans.
One easy way to check is if you are using an IDE with Bean detection capability to see if the IDE is picking up the bean.
If this is working then please paste in your code of the xml with bean in it and xml containg your scan ability.

Struts 2 action method intercepting using Spring AOP

I'm trying to intercept the Struts2 Action class's methods to print the method start and method end indication statement using Spring AOP.
The fact is , my Struts2 actions instance are also Spring beans (Struts2 and Spring integration done as per the url: http://www.mkyong.com/struts2/struts-2-spring-integration-example/). AOP configurations is as below:
<bean id="testAdviceBean" class="com.tcs.oss.plugins.SimpleAdvice">
</bean>
<aop:config>
<aop:aspect ref="testAdviceBean" order="200">
<aop:pointcut id="testPoint2"
expression="execution(java.lang.String com.test..DeviceAction.*(..))"
/>
<aop:around pointcut-ref="testPoint2" method="loggingAdvice" />
</aop:aspect>
</aop:config>
In the advice method loggingAdvice , I'm trying to print the method START and method END statement using the ProceedingJoinPoint API.The advice method is not called at all ... instead it's ending up with the error below after going through the struts default interceptor chain ...
But I'm getting the below ERROR TRACE:
09:26:49,093 TRACE
[org.springframework.beans.factory.support.DefaultListableBeanFactory]
(http-01h3463916-172.20.211.235-8543-5) Ignoring constructor [public
org.apache.struts2.dispatcher.ServletDispatcherResult(java.lang.String)]
of bean 'org.apache.struts2.dispatcher.ServletDispatcherResult':
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name
'org.apache.struts2.dispatcher.ServletDispatcherResult': Unsatisfied
dependency expressed through constructor argument with index 0 of type
[java.lang.String]: : No matching bean of type [java.lang.String]
found for dependency: expected at least 1 bean which qualifies as
autowire candidate for this dependency. Dependency annotations: {};
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
matching bean of type [java.lang.String] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for
this dependency. Dependency annotations: {}
09:26:49,095 TRACE
[org.springframework.beans.factory.support.DefaultListableBeanFactory]
(http-01h3463916-172.20.211.235-8543-5) Not autowiring property
'urlHelper' of bean
'org.apache.struts2.dispatcher.ServletDispatcherResult' by name: no
matching bean found
09:26:49,100 DEBUG
[org.apache.struts2.dispatcher.ServletDispatcherResult]
(http-01h3463916-172.20.211.235-8543-5) Forwarding to location
/General/error.jsp
If I just remove the above AOP configurations, It's just working fine. What I'm doing wrong ?
The advice method is not called because Action class was extending from ActionSupport class which in turn has a interface implementations... So , in this case, A JDK proxy was created for the Action class -- This type of proxy doesn't have any method specific(non-inheritance) to the Action class.
Adding proxy-target-class="true" attribute, in the AOP configuration, made the Spring to generate CGLib(need to add CGLib in the Classpath) based proxy.. which now has the non-inheritance methods too, of the Action class.
After a bunch of digging, I think I found the issue (if you're using Spring to help with AOP, even if you're not you're probably going to need a different ObjectFactory), long and short of it is that you need to make sure that the struts ObjectFactory is setup properly:
<constant name="struts.objectFactory" value="org.apache.struts2.spring.StrutsSpringObjectFactory" />
<constant name="struts.objectFactory.spring.autoWire.alwaysRespect" value="true"/>
or
<constant name="struts.objectFactory" value="spring" />
<constant name="struts.objectFactory.spring.autoWire.alwaysRespect" value="true"/>
source: http://www.javawebdevelop.com/3294124/

Mocking class in Spring 3.2 causes "No qualifying bean of type X" found

Im trying to mock the HttpClient implementation using the Spring 3.1 profiles and by using EasyMock, but the Spring container complains it cant find a bean with right type. Have I configured the mock wrong? If I replace the EasyMock bean with the actually implementation it is injected correctly, it seems like the EasyMock method doesnt create a bean of right type. All help very appreciated!
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.apache.http.client.HttpClient] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:986)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:856)
<beans profile="development,developmentthomas,test,integration,webtest,accept">
<bean id="httpClient" class="org.easymock.EasyMock" factory-method="createMock">
<constructor-arg value="org.apache.http.client.HttpClient" />
</bean>
</beans>
<beans profile="thomasciserver,testserverlocaloleg,testservercioleg,preprod,production,testservercithomas,testserverlocalthomas,localthomasclean,testserver,productionthomas">
<bean id="httpClient" class="org.apache.http.impl.client.DefaultHttpClient"/>
</beans>
i think the problem lies within the factory method.
have a look at this post Autowiring of beans generated by EasyMock factory-method? ithink this will solve your problem
See the spring-test. It has org.springframework.mock.http.client.MockClientHttpRequest. The org.springframework.mock package has a whole bushel of things that will save you from reinventing the wheel.

How to import Java-config class into XML-config so that both contexts have beans?

I have a project where I need to bootstrap #Configuration java-config classes into the XML configuration.
To do that, I'm reading that I also need to include the following bean definition (along with the bean definitions of the classes annotated with #Configuration).
<bean class="org.springframework.config.java.process.ConfigurationPostProcessor" />
But, I end up receiving the following error:
Caused by: java.lang.ClassNotFoundException: org.springframework.config.java.process.ConfigurationPostProcessor
I have to assume I'm missing a jar somewhere, but my various web searches hasn't resulted in an answer yet. Any help would be greatly appreciated. Thanks.
EDIT: Evidently, I was reading old documentation, which is no longer current. Let me back up. My project contains older XML-based configuration. The newer code is all using 'Java-config'. With that said, the contexts are apparently completely separate. I'd like to 'import' a java-config class into the XML configuration, so that both contexts have those particular beans. Does anyone know how I can do that?
This actually ended up being fairly simple. To get a Java-config bean definition into the xml-config, simply define the Java-config class as a bean within the XML-config. There are no extra jars necessary.
#Configuration
public class SomeJavaConfig {
#bean
... [bean definition]
}
inside the XML-config, you define this class as a bean.
<!-- needed to pick up the annotated java-config -->
<context:annotation-config />
<!-- Importing java-config class, which are annotated with #Configuration -->
<bean name="SomeJavaConfig" class="[fully qualified path].SomeJavaConfig" />
The XML-config, which may be part of a different context, now has all the bean definitions defined within the JavaConfig class.
UPDATED - to included Alan Franzoni's comment below in the answer.
Alternatively to annotation-config you can use component-scan. Then you do not have to include the Configuration Bean in XML:
<context:component-scan base-package="[fully qualified package path]" />
See Difference between <context:annotation-config> vs <context:component-scan> for more details.
Should be in:
spring-javaconfig-<version>.jar

Resources