NoClassDefFoundError with spring cache and aspectj - java

I am getting this error in my spring webapp (spring 3.1), and I don't know why.
org.springframework.web.util.NestedServletException: Handler
processing failed; nested exception is java.lang.NoClassDefFoundError:
mypackage/TestCache$AjcClosure1
(the $AjcClosure1 is weird)
If I comment the annotation #Cacheable in the class below the error is gone.
public class TestCache {
#Cacheable(value ="myCache")
public List<String> getDummyList(){
Logger l = Logger.getLogger(this.getClass());
l.error("calling getDummyList");
ArrayList<String> foo = new ArrayList<String>();
foo.add("foo");
foo.add("bar");
return foo;
}
}
My controller class (simplified):
#Controller
#RequestMapping("/mypage")
public class MyController {
#RequestMapping
public String index(ModelMap model, Locale locale) {
TestCache tc = new TestCache();
...
}
}
Application Context (only cache part):
<cache:annotation-driven mode="aspectj"/>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache"/>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="classpath:ehcache.xml"/>
I tried proxy and aspectj mode (in proxy mode less error but the cache was doing nothing)
This web application was built initially with roo and use spring mvc and webflow. So there is quite a lot of xml in the applicationContext.xml or webmvc-config.xml (and I am not able to understand what some beans are doing).
I am running the wepapps in eclipse with m2e-wtp and the pom.xml is using the plug-in aspectj-maven-plugin (but no idea what it does)
It looks like the issue is related with aspectj, but I never used aspectJ.
If anyone spring/java/aspectj guru can explain me what is making this error and how I can make my cache working it would be awesome! (I could find only tutorial but no sample project using the cacheable annotation).

It seems that the problem comes from the fact that all the class$AjcClosure[n].class aren't published and the only way to do it is remove, the webapps, clean start and republish the webapp.

One problem (may not the one that causes the NoClassDefFoundError) is that you can use Spring Functions like #Cacheable only for Spring Beans. So if you create an class via new (and this class it not annotated by #Configurable) then this is a normal class and not a Spring bean. Therefore the annotation is ignored in proxy mode. -- May this will also result in this stange error in AspectJ mode, but I don't know.

Related

Non Singleton (prototype) Spring beans JMX moniterable

I'm newbie to Spring JMX. And i want to monitor the prototype beans in my project through Spring JMX, I created a sample project to register a bean(Singleton) with Spring's MbeanExporter that is working. Then i googled to register the Non-Singleton bean with Spring JMX and monitor it but i didn't found any thing helpful.
I came across a Spring forum post that describes my problem but that answer is not to the point.
I kept googling for this issue and i found few posts on the stackoverlow itself that really helped me. Just copying the code here:-
#Component("MyPrototypeScopedBeanName")
#Scope(value = "prototype")
#ManagedResource
public class MyPrototypeScopedBeanName implements SelfNaming
#Autowired
MBeanExporter exporter;
.
.
#PostConstruct
private void init() throws Exception {
exporter.registerManagedResource(this);
}
.
.
.
#Override
public ObjectName getObjectName() throws MalformedObjectNameException {
return new ObjectName("com.foobar", "name", this.toString());
}
Also, you may want to configure your exporter to ignore this during autodetect, because the way autodetect works with prototypes, it will create yet another instance for itself that will add an additional instance to your JMX console.
<property name="autodetect" value="true"/>
<!-- Done to prevent creation of additional prototype during autodetect routine -->
<property name="excludedBeans">
<list>
<value>MyPrototypeScopedBeanName</value>
</list>
</property>
Stackoverflow link
Another link
Courtesy:- #theJC

Spring 4 Webservice HTTP 500 - IllegalStateException: The mapped controller method class is not an instance of the actual controller bean

so I am working on a school project and I am trying to build a JSON Rest Webservice application. I am using Spring 4 and Hibernate 4 with Jackson 2.
I have a lot of hard times with this app, but now I have a problem I cannot overgo. I am using Cloudbees as my cloud service provider and from time to time (which is important to state, because it sometimes work and sometimes not!) I get a HTTP 500 error :/.
The best part is - I never had it locally.
It goes more or less like this:
HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalStateException: The mapped controller method class 'pl.lodz.pp.controllers.crud.impl.UserController' is not an instance of the actual controller bean instance 'com.sun.proxy.$Proxy47'. If the controller requires proxying (e.g. due to #Transactional), please use class-based proxying.
And I am so confused. I never get this locally and usually if I restart the application on cloud (one or more time) it will work for some time again.
I had made some errors, like
#Autowire
private ClassType variable
instead of
#Autowire
private ClassInterface variable
but I fixed them all. I am NOT USING #Transactional annotation anymore. At least not in my class. Maybe the GenericDao have it somewhere (https://code.google.com/p/hibernate-generic-dao/) but I never had this problem before.
Transaction management:
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
Please, find the full code here:
https://github.com/atais/PP-JSON
Bottom line
I am not using #Transactional and I inject everything with the Interface type. So what am I possibly doing wrong? And what's the best - it works sometimes, but sometimes I get this error :/
The only thing you need to do is to add
#EnableAspectJAutoProxy(proxyTargetClass = true)
to your Spring Configuration.
In many cases the framework applies for your classes some proxying mechanisms: TX, Cache, Async etc. - depends on annotations, which you are using on your classes or its methods.
So it is good practice to introduce for those classes interfaces and use exactly that contract, not classes.
I understand that it looks like overhead for all #Service classes, but introduce interfaces at least for those classes which use some AOP aspects
I got the same exception when i implemented a interface (controller extends x implements interface) in my controller. Removing the interface solved the problem. I suspect implementing a specific interface is not supported for controllers.

Properties Handling With Seam In A Spring-like fashion

One of the Spring features I like the most is how you can handle properties loaded from a file. You only to need to set up a bean like the one below
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
Now you are able to inject the properties values loaded from the app.properties into your beans by using either xml (see below) or annotations.
<bean class="com.example.PersonDaoImpl">
<property name="maxResults" value="${results.max}"/>
</bean>
results.max is one of the properties.
I'm great fan of this feature because it enables me to create quite flexible applications that I can turn on/off some functionality by only changing one property - without redeploying the app.
Now I'm working with JBoss Seam and I've been struggling to find a way to do something similar using this framework.
Does anyone know how to do it? If not, does anyone have any idea of how I could handle properties in a nice way using Seam (I have seen some ways - but none of them were good enough).
Thanks.
If there's no appropriate way using you software stack (is there really no dependency injection!?). I'd say: Use Google Guice (https://code.google.com/p/google-guice/ , https://code.google.com/p/google-guice/wiki/Motivation?tm=6)!
Bad thing with Guice: You may have to read a lot to understand how it works, and what you can do with it. But after it's running you will simply inject your Properties object where you need it:
class YourClass {
#Inject Properties myProperties;
#Inject
public YourClass() { ... }
public void someMethod() {
use the property
}
}
or if you need the properties inside the constructor, you could also do:
class YourClass {
final Properties myProperties;
#Inject
public YourClass(Properties myProperties) {
this.myProperties = myProperties;
}
public void someMethod() {
use the property
}
}
Using Guice maybe enforces you to refactor your whole app.
But if you already have some DI framework, you should simply use that :)

How to achieve conditional resource import in a Spring XML context?

What I would like to achieve is the ability to "dynamically" (i.e. based on a property defined in a configuration file) enable/disable the importing of a child Spring XML context.
I imagine something like:
<import condition="some.property.name" resource="some-context.xml"/>
Where the property is resolved (to a boolean) and when true the context is imported, otherwise it isn't.
Some of my research so far:
Writing a custom NamespaceHandler (and related classes) so I can register my own custom element in my own namespace. For example: <myns:import condition="some.property.name" resource="some-context.xml"/>
The problem with this approach is that I do not want to replicate the entire resource importing logic from Spring and it isn't obvious to me what I need to delegate to to do this.
Overriding DefaultBeanDefinitionDocumentReader to extend the behaviour of the "import" element parsing and interpretation (which happens there in the importBeanDefinitionResource method). However I'm not sure where I can register this extension.
Prior to Spring 4, the closest you can get using standard Spring components is:
<import resource="Whatever-${yyzzy}.xml"/>
where ${xyzzy} interpolates a property from the system properties. (I use a hacky custom version of the context loader class that adds properties from other places to the system properties object before starting the loading process.)
But you can also get away with importing lots of unnecessary stuff ... and use various tricks to only cause the necessary beans to be instantiated. These tricks include:
placeholder and property substitution
selecting different beans using the new Spring expression language,
bean aliases with placeholders in the target name,
lazy bean initialization, and
smart bean factories.
This is now completely possible, using Spring 4.
In your main application content file
<bean class="com.example.MyConditionalConfiguration"/>
And the MyConditionalConfiguration looks like
#Configuration
#Conditional(MyConditionalConfiguration.Condition.class)
#ImportResource("/com/example/context-fragment.xml")
public class MyConditionalConfiguration {
static class Condition implements ConfigurationCondition {
#Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.PARSE_CONFIGURATION;
}
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// only load context-fragment.xml if the system property is defined
return System.getProperty("com.example.context-fragment") != null;
}
}
}
And then finally, you put the bean definitions you want included in the /com/example/context-fragment.xml
See the JavaDoc for #Conditional
As mentioned earlier, this can be easily accomplished with profiles if you're using Spring 3.1+
<!-- default configuration - will be loaded if no profile is specified -->
<!-- This will only work if it's put at the end of the configuration file -->
<!-- so no bean definitions after that -->
<beans profile="default">
<import resource="classpath:default.xml" />
</beans>
<!-- some other profile -->
<beans profile="otherProfile">
<import resource="classpath:other-profile.xml" />
</beans>
otherProfile can be easily activated with e.g.
mvn install -Dspring.profiles.active=otherProfile
if you're using different profiles in tests, just add -DforkMode=never to make sure that the tests will run inside same VM, therefore the param spring.profiles.active wont be lost
With Spring 3.1.x you can use bean profiles to achieve conditional resource import and bean instantiation. This is of course of no help if you are using an earlier version :)
For the record, Robert Maldon explains how to accomplish conditional definition of beans in this post: http://robertmaldon.blogspot.com/2007/04/conditionally-defining-spring-beans.html. It is a bit long to copy it here (besides, I don't think I should copy-paste his article anyway).
The end result with this approach, adapted for your example, is:
<condbean:cond test="${some.property.name}">
<import resource="some-context.xml"/>
</condbean:cond>
It is certainly not so simple as Stephen C's solution, but it is much more poweful.
Another one to consider for Spring 3.0:
<alias name="Whatever" alias=""Whatever-${yyzzy}" />
where ${xyzzy} interpolates a property from the system properties.
Another option is to have your app load a modules-config.xml file that is located in the /conf folder and edit it during the install/config phase to uncomment the modules you want loaded.
This is the solution I'm using with a web application that serves as a container for different integration modules. The web application is distributed with all the different integration modules. A modules-config.xml is placed in tomcat's /conf folder and the conf folder is added to the classpath (via catalina.properties/common.loader property). My web app webapp-config.xml has a <import resource="classpath:/modules-config.xml"/> to get it loaded.
You can override contextInitialized(javax.servlet.ServletContextEvent event) in your own ContextLoaderListener and set required System property before super.contextInitialized(event) called like this
package com.mypackage;
import org.springframework.web.context.ContextLoaderListener;
public class MyContextLoaderListener extends ContextLoaderListener {
public void contextInitialized(javax.servlet.ServletContextEvent event) {
System.setProperty("xyz", "import-file-name.xml");
super.contextInitialized(event);
}
}
And than replace ContextLoaderListener to MyContextLoaderListener in your web.xml
<listener>
<listener-class>com.mypackage.MyContextLoaderListener</listener-class>
</listener>
Now you can use in your spring.xml
<import resource="${xyz}" />
I hope this will help.

What is the cleanest way to autowire Spring Beans in a JSP?

We're currently adding some new features to an old webapp which was using only JSP without any framework for the front. We have added Spring recently, and we would like to autowire our beans in our modified JSP, while not rewriting everything to use SpringMVC, Struts2 or Tapestry5.
We're using autowiring by type, so it leads to get some code like this in the JSP, while previously getting the web application context ( as "wap") :
MyDao myDao = (MyDao) wap.getBeansOfType(MyDao.class).values().toArray()[0];
We would like not to use such a code but rather automagically inject our beans directly in our JSPs as we would in a business bean using #Autowired annotation.
In fact we're looking to the cleanest ways to inject our beans in our JSPs. What do you use ?
You can use Spring's ContextExposingHttpServletRequest:
HttpServletRequest decorator that
makes all Spring beans in a given
WebApplicationContext accessible as
request attributes, through lazy
checking once an attribute gets
accessed.
This would require your controller code to wrap the original HttpServletRequest in a ContextExposingHttpServletRequest, and then forward that to the JSP. It can either expose specific named beans, or every bean in the context.
Of course, this just shifts the problem from your JSPs to your controller code, but that's perhaps a more manageable problem.
You can't use #Autowired directly because both your jsps and servlets are instantiated by the servlet conainer. So they are not part of the spring context and hence their dependencies aren't injected.
You can:
move all code that to pure servlets, rather than in jsps - leave only presentation in the jsps.
use #Configurable on your servlets (and add a javaagent, as described in the linked docs)
Another way, is to make the servlet part of the current context manually. This is possible in both jsps and servlets:
public void init() {
WebApplicationContext ctx = WebApplicationContextUtils
.getRequiredWebApplicationContext(getServletContext());
AutowireCapableBeanFactory bf = ctx.getAutowireCapableBeanFactory();
bf.autowireBean(this);
}
This will resolve the #Autowired annotated dependencies.
Now, I'm not sure whether servlet containers are required to use only one instance of a servlet class. If not, you'd better place the above code in a getter-method for the dependency (getDao()) and if the #Autowired property is null (i.e. another instance of the servlet-class is used by the container) - perform the above operation.
That all said, really consider using a web framework (any of the ones you listed). Having logic in jsps is completely wrong, hard to support, hard to read, etc.
What about overriding jspInit() method and adding Autowiring support:
<%# page import="com.example.ExampleService"%>
<%# page import="org.springframework.beans.factory.annotation.Value"%>
<%# page import="org.springframework.beans.factory.annotation.Autowired"%>
<%# page import="org.springframework.web.context.support.SpringBeanAutowiringSupport"%>
<%!
public void jspInit()
{
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,
getServletContext());
}
#Value("${example.property}")
private String someField;
#Autowired
private ExampleService exampleService;
%>
<% final Object data = exampleService.getSomething(someField); %>
I doubt that there is a clean way to inject dependencies into a JSP.
I think that the clean solution would be to start refactoring your code to get the business logic out of the JSPs, using either SpringMVC or one of the alternatives you cited.
Start with one or more minimalist controllers that simply pass the request to the JSPs with the injected beans as attributes; #skaffman's answer gives one way to do that, or you could do it more selectively. Then progressively migrate code out of the JSPs and into the controllers.
This isn't autowired, but Spring can expose your bean names into the request context, you just need to configure it in the viewResolver.
From: https://raibledesigns.com/rd/entry/spring_mvc_jstlview_and_exposecontextbeansasattributes
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="exposeContextBeansAsAttributes" value="true"/>
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>

Categories