I was using spring to create objects through beans. Now I tried to use aop to create the same object and I get $Proxy cannot be cast to SaleRoom exception.
the previous xml was:
<?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:aop="http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
xmlns:context="http://www.springframework.org/schema/context/spring-context-2.5.xsd"
xmlns:flow="http://www.springframework.org/schema/webflow-config/spring-webflow-config- 1.0.xsd"
xmlns:jm s="http://www.springframework.org/schema/jms/spring-jms-2.5.xsd"
xmlns:jee="http://www.springframework.org/schema/jee/spring-jee-2.5.xsd"
xmlns:lang="http://www.springframework.org/schema/lang/spring-lang-2.5.xsd"
xmlns:osgi="http://www.springframework.org/schema/osgi/spring-osgi.xsd"
xmlns:tx="http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
xmlns:util="http://www.springframework.org/schema/util/spring-util-2.5.xsd"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/aop/spring-aop-2.5.xsd/spring-spring-aop-2.5.xsd-2.5.xsd
http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/context/spring-context-2.5.xsd/spring-spring-context-2.5.xsd-2.5.xsd
http://www.springframework.org/schema/webflow-config/spring-webflow-config-1.0.xsd http://www.springframework.org/schema/webflow-config/spring-webflow-config-1.0.xsd/spring-spring-webflow-config-1.0.xsd-2.5.xsd
http://www.springframework.org/schema/jms/spring-jms-2.5.xsd http://www.springframework.org/schema/jms/spring-jms-2.5.xsd/spring-spring-jms-2.5.xsd-2.5.xsd
http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/jee/spring-jee-2.5.xsd/spring-spring-jee-2.5.xsd-2.5.xsd
http://www.springframework.org/schema/lang/spring-lang-2.5.xsd http://www.springframework.org/schema/lang/spring-lang-2.5.xsd/spring-spring-lang-2.5.xsd-2.5.xsd
http://www.springframework.org/schema/osgi/spring-osgi.xsd http://www.springframework.org/schema/osgi/spring-osgi.xsd/spring-spring-osgi.xsd-2.5.xsd
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/tx/spring-tx-2.5.xsd/spring-spring-tx-2.5.xsd-2.5.xsd
http://www.springframework.org/schema/util/spring-util-2.5.xsd http://www.springframework.org/schema/util/spring-util-2.5.xsd/spring-spring-util-2.5.xsd-2.5.xsd
">
<bean id="sale01" class="application.common.entities.BidRoom">
<property name="itemId" value="0001"/>
<property name="lifeTime" value="15"/>
</bean>
</beans>
And I used the following code to create the sales:
ApplicationContext context = new FileSystemXmlApplicationContext(SalesManager.getSalesSourceFile());
SaleRoom saleRoom;
List<String> salesNames = new LinkedList<String>();
List<SaleRoom> allSales = new LinkedList<SaleRoom>();
// Get all sales id's for beans
NodeList salesNodeList = salesDoc.getElementsByTagName("bean");
for (int i = 0; i < salesNodeList.getLength(); i++) {
Node nNode = salesNodeList.item(i);
salesNames.add(((Element) nNode).getAttribute("id").toString());
}
for (String saleName : salesNames) {
if(saleName.contains("sale")) {
saleRoom = (SaleRoom) context.getBean(saleName);
allSales.add(saleRoom);
}
}
return allSales;
This is the new 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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<aop:aspectj-autoproxy>
<aop:include name="logSettersCalls"/>
</aop:aspectj-autoproxy>
<bean id="logSettersCalls" class="application.logging.aop.LogSettersCalls"/>
<bean id="sale01" class="application.common.entities.BidRoom">
<constructor-arg index="0" type="int" value="0001"/>
<constructor-arg index="1" type="int" value="15"/>
</bean>
</beans>
The Aspect logging class:
#Aspect
public class LogSettersCalls {
#Pointcut("execution(void set*(*))")
public void setMethod() {}
#Before("setMethod()")
public void logSetterCall(JoinPoint theJoinPoint) {
String methodName = theJoinPoint.getSignature().getName();
Object newValue = theJoinPoint.getArgs()[0];
Object theObject = theJoinPoint.getTarget();
System.out.println("The method " + methodName + " is called on object "
+ theObject + " with the value " + newValue);
}
}
I'm using the same code for creating the beans via aop. and I get
Exception in thread "main" java.lang.ClassCastException: $Proxy11 cannot be cast to application.common.entities.SaleRoom
The line that throws the exception:
saleRoom = (SaleRoom) context.getBean(saleName);
Any help will be appreciated. Thanks.
Does your SaleRoom class implement some interface? If yes, then you should use interface and not class in you code:
ISaleRoom saleRoom = (ISaleRoom) context.getBean(saleName);
Because if your bean implements some interface then Spring by default will create proxy based on this interface.
Here is a good article about proxy creation in Spring.
Also you can change proxying mechanism for Spring AOP if you want to create proxy for target class. This is described here in reference documentation.
Related
I have a sample code in which I am trying to convert application-context.xml to Spring annotated Java class. How to add constructor-arg with proper annotations here. Could you please help me sort this.
application-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:context="http://www.springframework.org/schema/context"
xmlns:oxm="http://www.springframework.org/schema/oxm" xmlns:util="http://www.springframework.org/schema/util"
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 http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<context:component-scan base-package="myproject"/>
<!-- Define the SOAP version used by the WSDL -->
<bean id="soapMessageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
<property name="soapVersion">
<util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12"/>
</property>
</bean>
<!-- The location of the generated Java files -->
<oxm:jaxb2-marshaller id="marshaller" contextPath="myproject.wsdl.currency"/>
<!-- Configure Spring Web Services -->
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="soapMessageFactory"/>
<property name="marshaller" ref="marshaller"/>
<property name="unmarshaller" ref="marshaller"/>
<property name="defaultUri" value="http://www.webservicex.net/CurrencyConvertor.asmx?WSDL"/>
</bean>
<bean id="example" class="org.project.Example"/>
I have created Config.class as below.
#Configuration
public class AppConfig {
#Bean(name="soapMessageFactory")
public SaajSoapMessageFactory getSoapMsgFactory() {
SaajSoapMessageFactory soapFactory = new SaajSoapMessageFactory();
soapFactory.setSoapVersion(SoapVersion.11);
return soapFactory;
}
#Bean(name="webServiceTemplate")
public WebServiceTemplate getWsTemplate(Marshaller marshaller, Unmarshaller unmarshaller) {
WebServiceTemplate wsTemplate = new WebServiceTemplate();
//how to configure the constructor-arg here
wsTemplate.setMarshaller(marshaller);
wsTemplate.setUnMarshaller(unmarshaller);
wsTemplate.setDefaultUri(http://www.webservicex.net/CurrencyConvertor.asmx?WSDL);
return wsTemplate;
}
#Bean(name="example")
public Example getExample() {
return new ExampleImpl();
}
This should work...
#Bean(name="soapMessageFactory")
public SaajSoapMessageFactory getSoapMsgFactory() {
SaajSoapMessageFactory soapFactory = new SaajSoapMessageFactory();
soapFactory.setSoapVersion(SoapVersion.11);
return soapFactory;
}
#Bean(name="webServiceTemplate")
public WebServiceTemplate getWsTemplate(SaajSoapMessageFactory soapFactory, Marshaller marshaller, Unmarshaller unmarshaller) {
WebServiceTemplate wsTemplate = new WebServiceTemplate(soapFactory);
wsTemplate.setMarshaller(marshaller);
wsTemplate.setUnMarshaller(unmarshaller);
wsTemplate.setDefaultUri(http://www.webservicex.net/CurrencyConvertor.asmx?WSDL);
return wsTemplate;
}
When you specify any dependecy in #Bean method, spring will search for that bean in its context.
Since SaajSoapMessageFactory is locally created and doesn't have any other dependency, you could just call it locally like this
WebServiceTemplate wsTemplate = new WebServiceTemplate(getSoapMsgFactory());
Gratitude: Thanks for your support.
Problem Description:
I am facing an exception while trying to run the below code. Don't even have a clue.
How to write the xml definition to initiate Dependent class using #Autowired Constructor with int parameter.
ExceptionMessage:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'dependent' defined in class path
resource [simple-context.xml]:
Could not resolve matching constructor (hint: specify index/type/name arguments
for simple parameters to avoid type ambiguities)
filename: spring-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:c="http://www.springframework.org/schema/c"
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.learning.spring.constinjection" />
<bean id="dependency" class="com.learning.spring.constinjection.Dependency"></bean>
<bean id="dependent" class="com.learning.spring.constinjection.Dependent">
<constructor-arg ref="dependency" name="dpcy" />
<constructor-arg name="mesg" value="Hi this is a test mesg" />
</bean>
<bean id="dependent2" class="com.learning.spring.constinjection.Dependent"
c:mesg="Hi, this is another test mesg" />
</beans>
filename: Dependent.java
public class Dependent {
Dependency dpcy;
Dependent(Dependency dpcy, String mesg){
this.dpcy = dpcy;
System.out.println("Message is: " + mesg);
}
Dependent(String mesg){
System.out.println("Only Message is: " + mesg);
}
#Autowired
Dependent(Integer ticketno){
System.out.println("Ticket no is: " + ticketno);
}
}
filename: Dependency.java
public class Dependency {
Dependency(){
System.out.println("Dependency loaded successfully");
}
}
filename: ConstructorInjectionApp
public class ConstructorInjectionApp {
public static void main(String[] args) {
GenericXmlApplicationContext gen = new GenericXmlApplicationContext();
gen.load("classpath:simplespringconstinjection.xml");
gen.refresh();
Dependent d = (Dependent) gen.getBean("dependent");
Dependent d2 = (Dependent) gen.getBean("dependent2");
}
}
By changing this:
<bean id="dependent" class="com.learning.spring.constinjection.Dependent">
<constructor-arg ref="dependency" name="dpcy" />
<constructor-arg name="mesg" value="Hi this is a test mesg" />
</bean>
to this:
<bean id="dependent" class="com.learning.spring.constinjection.Dependent"
c:dpcy-ref="dependency" c:mesg="Hi, this is another test mesg" />
I was able to get the ApplicationContext to properly initialize with no errors.
See this Spring doc for information on the "c" namespace.
There is still an issue with the constructor with the #Autowired annotation.
this is my Controller:
#Controller
public class WebRedirectController {
#RequestMapping(value = "/welcome", method = RequestMethod.GET)
public String welcome() {
return "welcome";
}
#RequestMapping(value = "/redirect", method = RequestMethod.GET)
public String redirect() {
return "redirect:finalPage";
}
#RequestMapping(value = "/finalPage", method = RequestMethod.GET)
public String finalPage() {
return "final";
}
}
servletContext.xml:
<beans xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
xsi:schemalocation="
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- Enable annotation driven controllers, validation etc... -->
<mvc:annotation-driven></mvc:annotation-driven>
<context:component-scan base-package="com.dineshonjava.controller">
</context:component-scan>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="viewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
This Exception I am getting when i run the application :
Line 10 in XML document from ServletContext resource [/WEB-INF/config/sdnext-servlet.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 10; columnNumber: 65; cvc-elt.1: Cannot find the declaration of element 'beans'.
please tell me where i am doing mistake i try to solve this issue but still unable to fix please suggest me .
I think you should add this in your XML document
contextConfigLocation
/WEB-INF/classes/applicationContext.xml
I'm trying to get Memcache working in Spring.
I've setup a local Memcached server using Docker and Kitematic:
I can access the Memcached server using telnet: telnet 192.168.99.100 32780 and then run stats or stats items (which only prints out END if the cache is empty);
My pom.xml:
<dependency>
<groupId>com.google.code.simple-spring-memcached</groupId>
<artifactId>simple-spring-memcached</artifactId>
<version>3.6.0</version>
</dependency>
<dependency>
<groupId>com.google.code.simple-spring-memcached</groupId>
<artifactId>spring-cache</artifactId>
<version>3.6.0</version>
</dependency>
<dependency>
<groupId>com.google.code.simple-spring-memcached</groupId>
<artifactId>xmemcached-provider</artifactId>
<version>3.6.0</version>
</dependency>
In my applicationContext.xml I have the following:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">
<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>
...
<import resource="cacheContext.xml" />
...
In cacheContext.xml my config is as follow:
<?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"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<aop:aspectj-autoproxy/>
<cache:annotation-driven/>
<context:component-scan base-package="com.google.code.ssm"/>
<context:component-scan base-package="com.mycee.application"/>
<bean id="cacheBase" class="com.google.code.ssm.aop.CacheBase"/>
<bean id="readThroughSingleCache" class="com.google.code.ssm.aop.ReadThroughSingleCacheAdvice">
<property name="cacheBase" ref="cacheBase"/>
</bean>
<bean id="readThroughMultiCache" class="com.google.code.ssm.aop.ReadThroughMultiCacheAdvice">
<property name="cacheBase" ref="cacheBase"/>
</bean>
<bean id="readThroughAssignCache" class="com.google.code.ssm.aop.ReadThroughAssignCacheAdvice">
<property name="cacheBase" ref="cacheBase"/>
</bean>
<bean id="updateSingleCache" class="com.google.code.ssm.aop.UpdateSingleCacheAdvice">
<property name="cacheBase" ref="cacheBase"/>
</bean>
<bean id="updateMultiCache" class="com.google.code.ssm.aop.UpdateMultiCacheAdvice">
<property name="cacheBase" ref="cacheBase"/>
</bean>
<bean id="updateAssignCache" class="com.google.code.ssm.aop.UpdateAssignCacheAdvice">
<property name="cacheBase" ref="cacheBase"/>
</bean>
<bean id="invalidateSingleCache" class="com.google.code.ssm.aop.InvalidateSingleCacheAdvice">
<property name="cacheBase" ref="cacheBase"/>
</bean>
<bean id="invalidateMultiCache" class="com.google.code.ssm.aop.InvalidateMultiCacheAdvice">
<property name="cacheBase" ref="cacheBase"/>
</bean>
<bean id="invalidateAssignCache" class="com.google.code.ssm.aop.InvalidateAssignCacheAdvice">
<property name="cacheBase" ref="cacheBase"/>
</bean>
<bean id="incrementCounterInCache" class="com.google.code.ssm.aop.counter.IncrementCounterInCacheAdvice">
<property name="cacheBase" ref="cacheBase"/>
</bean>
<bean id="decrementCounterInCache" class="com.google.code.ssm.aop.counter.DecrementCounterInCacheAdvice">
<property name="cacheBase" ref="cacheBase"/>
</bean>
<bean id="readCounterFromCache" class="com.google.code.ssm.aop.counter.ReadCounterFromCacheAdvice">
<property name="cacheBase" ref="cacheBase"/>
</bean>
<bean id="updateCounterInCache" class="com.google.code.ssm.aop.counter.UpdateCounterInCacheAdvice">
<property name="cacheBase" ref="cacheBase"/>
</bean>
<bean name="cacheManager" class="com.google.code.ssm.spring.SSMCacheManager">
<property name="caches">
<set>
<bean class="com.google.code.ssm.spring.SSMCache">
<constructor-arg name="cache" index="0" ref="defaultCache"/>
<constructor-arg name="expiration" index="1" value="300"/>
<constructor-arg name="allowClear" index="2" value="false"/>
</bean>
</set>
</property>
</bean>
<bean name="defaultCache" class="com.google.code.ssm.CacheFactory" depends-on="cacheBase">
<property name="cacheName" value="defaultCache"/>
<property name="cacheClientFactory">
<bean class="com.google.code.ssm.providers.xmemcached.MemcacheClientFactoryImpl"/>
</property>
<property name="addressProvider">
<bean class="com.google.code.ssm.config.DefaultAddressProvider">
<property name="address" value="localhost:11211"/>
</bean>
</property>
<property name="configuration">
<bean class="com.google.code.ssm.providers.CacheConfiguration">
<property name="consistentHashing" value="true"/>
</bean>
</property>
</bean>
</beans>
I've created three different methods, each using different caching mechanisms:
#Component("cacheEndpoint")
public class CacheClass {
#Autowired
SSMCacheManager cache;
public String getDateTime1(String anything) {
SSMCache c = cache.getCache("defaultCache");
String s = c.get(anything, String.class);
if (s != null) {
return s;
}
Date d = new Date();
String response = d.toString() + " - " + d.getTime();
c.put(anything, response);
return response;
}
#Cacheable("defaultCache")
public String getDateTime2(String anything) {
Date d = new Date();
String response = d.toString() + " - " + d.getTime();
return response;
}
#ReadThroughSingleCache(namespace = "defaultCache", expiration = 15000)
public String getDateTime3(String anything) {
Date d = new Date();
String response = d.toString() + " - " + d.getTime();
return response;
}
}
To access it I do:
#Autowired
CacheClass c;
...
// caches perfectly
c.getDateTime1("test");
// doesn't do any caching
c.getDateTime2("test");
// doesn't do any caching
c.getDateTime3("test");
After placing runtime exceptions in getDateTime2 and getDateTime3, it was established that the interceptors aren't being invoked.
Any idea what could be the cause of #Cachable and #ReadThroughSingleCache not doing their interception magic?
Update based on Matjaž Pečan's response:
CacheClass Interface:
public interface CacheClass {
public String getDateTime1(String anything);
public String getDateTime2(String anything);
public String getDateTime3(String anything);
}
CacheClass Implementation:
#Component("cacheEndpoint")
public class CacheClassImpl implements CacheClass {
#Autowired
SSMCacheManager cache;
public String getDateTime1(String anything) {
SSMCache c = cache.getCache("defaultCache");
String s = c.get(anything, String.class);
if (s != null) {
return s;
}
Date d = new Date();
String response = d.toString() + " - " + d.getTime();
c.put(anything, response);
return response;
}
#Cacheable("defaultCache")
public String getDateTime2(String anything) {
Date d = new Date();
String response = d.toString() + " - " + d.getTime();
return response;
}
#ReadThroughSingleCache(namespace = "defaultCache", expiration = 15000)
public String getDateTime3(String anything) {
Date d = new Date();
String response = d.toString() + " - " + d.getTime();
return response;
}
}
SOAP Endpoint where I'm testing the cache:
#Endpoint
public class PingEndpoint {
#Autowired
CacheClass c;
#ResponsePayload
#PayloadRoot(localPart = "PingRequest", namespace = "http://www.mycee.com/Application")
public PingResponse doPing(#RequestPayload PingRequest request) {
// caches perfectly
System.out.println(c.getDateTime1("test"));
// doesn't do any caching
System.out.println(c.getDateTime2("test"));
// doesn't do any caching
System.out.println(c.getDateTime3("test"));
}
}
cacheContext.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:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<aop:aspectj-autoproxy proxy-target-class="true"/>
<cache:annotation-driven/>
...
There is an error in SSM 3.6.0, please downgrade to 3.5.0 to solve the issue or try to add
depends-on="cacheBase"
to defaultCache bean definition.
Update 1
Self invocations don't work. A call won't be intercepted and result won't be cached if a invocation is through this object. Make sure that method defined in a bean is invoked from another Spring bean.
Update 2
For SSM method has to be annotated as below:
#ReadThroughSingleCache(namespace = "defaultCache", expiration = 15000)
public String getDateTime3(#ParameterValueKeyProvider String anything) {
...
}
Still interceptors for some reasons aren't triggered.
Spring proxying mechanisms differ depending on which implementation is used.
The default is AspectJ which requires interfaces (proxy-by-interface) and those interfaces will then be implemented by the actual proxy wrapped around your bean. Since your bean is only a class and does not have an interface, it is not proxied with AspectJ.
There are two possible solutions:
Implement an interface for CacheClass and use that interface in wiring to other beans
Use CGLib proxying (you will need to add a runtime dependency on CGLib) and add proxy-target-class in your aspectj-proxy element:
<aop:aspectj-autoproxy proxy-target-class="true"/>
I want to record execution time of my service method.
I think AOP is a easy way to do, so I wrote an Aspect:
#Aspect
public class ServiceLogAdviceAspect {
private static Logger LOG = LoggerFactory.getLogger(ServiceLogAdviceAspect.class);
#Around("execution(* com.j1.**.service.*(..))")
public Object doBasicProfilingTime(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
Object target = joinPoint.getTarget();
long start = System.currentTimeMillis();
Object retVal = joinPoint.proceed();
long end = System.currentTimeMillis();
LOG.error(String.format("Invoke [%s$%s] Takes %d ms", target.getClass().getCanonicalName(), methodName, (end - start)));
return retVal;
}
}
and Spring config:
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<aop:aspectj-autoproxy/>
<bean id="logAdviceAspect"
class="com.j1.soa.common.aspect.ServiceLogAdviceAspect"></bean>
</beans>
But when I invoke the method
public ServiceMessage<GoodsDetailDto> getGoodDetail(GoodsDetailDto goodsDetailDto)
I get neither error output nor into the breakpoint.
EDIT
getGoodDetail is defined in class
com.j1.soa.resource.item.service.GoodsDetailServiceImpl
And I am calling it using Hessian RPC,
First defined spring bean of Remote Service in application-context-rpc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="goodsDetailService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
<property name="serviceUrl" value="http://api.soa.item.j1.com/hessian/goodsDetailService" />
<property name="serviceInterface" value="com.j1.soa.resource.item.api.GoodsDetailService" />
<property name="readTimeout" value="6000"/>
</bean>
</beans>
Then defined it in client
#Autowired
private GoodsDetailService goodsDetailService;
And using it
GoodsDetailDto goodsDetailDto = new GoodsDetailDto();
goodsDetailDto.setGoodsId(NumericUtil.parseLong(goodsId));
goodsDetailDto.setProductId(NumericUtil.parseInt(productId));
goodsDetailDto.setSiteType(SiteType.MOBILE);
ServiceMessage<GoodsDetailDto> detailResult = goodsDetailService
.getGoodDetail(goodsDetailDto);
You should include logAdviceAspect in <aop:aspectj-autoproxy/>
<aop:aspectj-autoproxy>
<aop:include name="logAdviceAspect"/>
</aop:aspectj-autoproxy>