Here is situation:
We have class with defined aspect to it's methodA;
We have JUnit test for this methodA;
When I run JUnit test it activates Aspect as well. Any thoughts how to ignore Aspects during unit tests?
I have separated tests for my Aspects and it works fine. So in my unit test I want to test only methodA without any attached aspects.
I use spring 3.0 and its aspectj support.
Thanks in advance.
Regards,
Max
You can disable the compile-time weaving that I assume your IDE is doing and use load-time weaving in your separated AspectJ tests.
To enable load-time weaving you have to provide a javaagent as an JVM parameter.
An example:
-javaagent:lib/spring-dependencies/spring-agent.jar
Other changes when you move from compile-time to load-time weaving
You must also provide an aop.xml file in the META-INF folder on the claspath.
For my trace example, it looks like this:
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only weave classes in this package -->
<include within="aspects.trace.demo.*" />
</weaver>
<aspects>
<!-- use only this aspect for weaving -->
<aspect name="aspects.trace.TraceAspect" />
</aspects>
</aspectj>
In this configuration you can see that the TraceAspect class will be weaved with all the classes in the demo package.
Spring configuration with load-time weaving
<?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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="traceAspect" class="aspects.trace.TraceAspect"
factory-method="aspectOf"/>
<context:load-time-weaver />
</beans>
The configuration file is almost the same as the compile-time configuration file, except it also contains a load-time weaver element.
I hope this helps!
Related
I have an application that was tested with Cucumber, but since upgrading (Cucumber 1.1.6 to 1.2.5, java 1.6 to 1.8, Spring 3.2.0 to 4.2.6) it no longer works because it complains about Annotations differs on glue classes found
The structure is as follows:
Some common stepdefs which need some property values
More specific stepdefs which require some #ContextConfiguration
Both of these should also share a bean.
The common part will never be run on its own. But I have multiple tests each using their own specific stepdefs. This now refuses to run because of Annotations differs on glue classes found.
Is there a way to get this to run without polluting the common context with the specifics of the concrete context?
The step definitions:
#ContextConfiguration("classpath:cucumber-common.xml")
public class CommonStepdefs {
#Autowired
private SharedBean sharedBean;
#Value("${some.property}")
private String someProperty;
// actual step def methods
}
#ContextConfiguration("classpath:cucumber-concrete.xml")
public class ConcreteStepdefs {
#Autowired
private SharedBean sharedBean;
#Autowired
private OtherBean otherBean;
// actual step def methods
}
The common Spring configuration:
<?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:property-placeholder location="classpath:com/example/cucumber-common.properties"/>
<context:spring-configured/>
<context:annotation-config/>
<bean id="glueCodeScope" class="cucumber.runtime.java.spring.GlueCodeScope"/>
<bean id="glueCodeScopeConfigurer" class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="cucumber-glue" value-ref="glueCodeScope"/>
</map>
</property>
</bean>
<bean id="sharedBean" class="com.example.SharedBean" scope="cucumber-glue"/>
</beans>
The other Spring configuration (which imports the common one):
<?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">
<import resource="classpath:cucumber-common.xml"/>
<context:spring-configured/>
<context:annotation-config/>
<context:component-scan base-package="com.example.rest"/>
<!-- more bean definitions -->
</beans>
The tests are run using:
#RunWith(Cucumber.class)
#CucumberOptions(
format = { "html:target/cucumber-html-report", "json:target/cucumber-json-report.json" },
glue = { "com.example.common", "com.example.concrete" },
monochrome = true,
strict = true)
You can use qaf-gherkin which simplifies implementation for this kind of requirement. With QAF you can achieve without using spring. It also supports steps from packaged jar. If you have common steps in one package and platform specific steps in different package your configuration may look like below:
step.provider.pkg=com.myapp.steps.common;com.myapp.steps.web
In case if you want to run together with you can specify in TestNG xml config file as below:
<test name="Test-web">
<parameter name="step.provider.pkg" value="com.myapp.steps.common;com.myapp.steps.web" />
<parameter name="scenario.file.loc" value="resources/features" />
<classes>
<class name="com.qmetry.qaf.automation.step.client.gherkin.GherkinScenarioFactory" />
</classes>
</test>
<test name="Test-mobile">
<parameter name="step.provider.pkg" value="com.myapp.steps.common;com.myapp.steps.mobile" />
<parameter name="scenario.file.loc" value="resources/features" />
<classes>
<class name="com.qmetry.qaf.automation.step.client.gherkin.GherkinScenarioFactory" />
</classes>
</test>
One of the benefit is, common steps can be in jar which you can share across multiple projects. Like spring #Autowired, QAF supports #Inject annotation.
I need some help: I have one EAR-File, containing one WAR-File, one EJB-Jar-File and some "shared" libs:
aopalliance-1.0.jar commons-logging-1.1.1.jar log4j-1.2.16.jar spring-aop-4.0.5.RELEASE.jar spring-beans-4.0.5.RELEASE.jar spring-context-4.0.5.RELEASE.jar spring-context-support-4.0.5.RELEASE.jar spring-core-4.0.5.RELEASE.jar spring-expression-4.0.5.RELEASE.jar
The War File has a Context initializer which find the spring config and loads everything well.
I now want to use another Spring Context for the EJB Jar.
My EJB is defined as
#Stateless(mappedName = "ejb/SpringRocks")
#RemoteHome(com.ibm.websphere.ola.ExecuteHome.class)
#Interceptors(SpringBeanAutowiringInterceptor.class)
public class WolaUseCaseOne {
#Autowired
private DummyService dummyService;
/* ...More stuff here */
Inside the EJB-JAR, there is also a beanRefContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myEjb" name="myEjb" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg value="classpath*:META-INF/spring/simpleEjb.xml" />
</bean>
</beans>
The simpleEjb.xml is is also inside the EJB-Jar and is defining a very simple Bean:
<?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="myDummyService" class="com.provinzial.beispielanwendung.batch.wola.DummyServiceImpl" />
</beans>
As described, the WEB Part works perfect, but when the EJB is called, the SpringBeanAutowiringInterceptor is called, but seems to do nothing. What do I have to do, to get a Spring Context created?! My hope was that it is initialized when the EJB is created. I created a Subclass of SpringBeanAutowiringInterceptor with some loggers, but the class is only created, no method is called !
What else do I have to do? Or does anybody have a valid EAR File example?
I think the Problem is that inside the EJB Module no context is initialized...
Greets
Timo
I was facing similar issue with my EJB (no WAR). This is what fixed mine,
I was missing the spring-aop jar on my classpath. I see you have it so good there.
In my ejb-jar.xml file, I set the meta-data flag to true so I did not get prompted on deployment to complete.
I set to "false" for one deployment to see what IBM generated for me. In the ejb-jar.xml it added the following (my MDB is named TaskMDB),
<assembly-descriptor>
<interceptor-binding>
<ejb-name>TaskMDB</ejb-name>
<interceptor-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
<interceptors>
<interceptor>
<interceptor-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</interceptor-class>
<post-activate>
<lifecycle-callback-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</lifecycle-callback-class>
<lifecycle-callback-method>autowireBean</lifecycle-callback-method>
</post-activate>
<pre-passivate>
<lifecycle-callback-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</lifecycle-callback-class>
<lifecycle-callback-method>releaseBean</lifecycle-callback-method>
</pre-passivate>
<post-construct>
<lifecycle-callback-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</lifecycle-callback-class>
<lifecycle-callback-method>autowireBean</lifecycle-callback-method>
</post-construct>
<pre-destroy>
<lifecycle-callback-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</lifecycle-callback-class>
<lifecycle-callback-method>releaseBean</lifecycle-callback-method>
</pre-destroy>
</interceptor>
</interceptors>
Then I added what IBM generated (the assembly-descriptor and interceptors stanzas) back to my ejb-jar.xml and set the metadata-complete back to true.
Then it worked. Hope this helps.
Here is the full ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="3.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd">
<display-name>ares-api-uow-ejb</display-name>
<enterprise-beans>
<message-driven id="TaskMDB">
<ejb-name>TaskMDB</ejb-name>
<ejb-class>something.api.uow.ejb.mdb.TaskMDB</ejb-class>
<messaging-type>javax.jms.MessageListener</messaging-type>
<transaction-type>Bean</transaction-type>
</message-driven>
</enterprise-beans>
</ejb-jar>
I have spring bean with session scope and AOP CGLIB proxy.
<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:aop="http://www.springframework.org/schema/aop"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="restClient" class="com.test.services.RestClient" scope="session">
<constructor-arg ref="dataSource"/>
<aop:scoped-proxy /> <!--proxy-target-class="true" default is true to use cglib-->
</bean>
</beans>
In spring-aop-4.2.xsd its have <xsd:attribute name="proxy-target-class" type="xsd:boolean" default="true">
Are class-based (CGLIB) proxies to be created? This is the default; in
order to switch to standard Java interface-based proxies, turn this
flag to "false".
This means that default CGLIB proxy is created. But my maven project don`t have CGLIB dependency I have only spring-context and spring-web and in dependency diagram its have spring-aop but without transitive dependency to cglib. My project compiles and run without to have this dependency:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.1</version>
</dependency>
If its need to include cglib dependency or spring-aop v4.2.5 already have repackage cglib version?
Spring includes a repackaged version of cglib and only uses this version. It does not matter what version of cglib you are having on the class path. Only setting the flag matters.
I have a Spring / Hibernate application. Custom type created by Hibernate needs Spring context, so I use Spring Aspects to provide it.
#Configurable(preConstruction = true)
public class EncryptedStringUserType implements EnhancedUserType {
...
#EnableSpringConfigured
#EnableLoadTimeWeaving
public class RootConfiguration {
...
After adding Spring Security, I got number of messages in stderr like this:
[AppClassLoader#14dad5dc] error can't determine implemented interfaces of missing type org.springframework.security.ldap.authentication.LdapAuthenticationProvider
when weaving type org.springframework.security.config.annotation.authentication.configurers.ldap.LdapAuthenticationProviderConfigurer
when weaving classes
when weaving
[Xlint:cantFindType]
Is it possible to specify packages of classes that should be weaved and avoid trying to weaving other ones?
SOLUTION
Put META-INF/aop.xml to resources root and exclude unnecessary packages:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<exclude within="org.springframework.security.config.annotation.authentication.configurers.ldap.*"/>
<exclude within="org.springframework.security.config.annotation.web.configurers.openid.*"/>
</weaver>
</aspectj>
You can limit the scope of weaving by adding a <include within="your.package.here.*"/> tag to the META-INF/aop.xml file in your classpath. Here's a full example of META-INF/aop.xml taken from the Spring documentation:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only weave classes in our application-specific packages -->
<include within="foo.*"/>
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="foo.ProfilingAspect"/>
</aspects>
</aspectj>
This is an integration issue of Drools KIE and Spring MVC Web V 3.2.3 where google just isn't finding any references to so I'll try my luck here ...
I'm integrating Drools KIE and Spring 3.2.3.RELEASE (MVC Web)- and I'm getting the following error:
No setter found for property 'kBaseName' in class 'org.kie.spring.factorybeans.KBaseFactoryBean'
[config set: maven-spring-drools/web-context application-config.xml
/maven-spring-drools/src/main/resources/spring
The Project is a pure Maven project w/out any outside natures imposed upon it (aka. Drools/Spring).
It's complaining that it can't find the setters for the kBaseName', which is set here:
I'm using a kmodule.xml found in the META-INF dir under the src/main/resources dir.
Can anyone help me discover the disconnect?
Moreover - do I have to do it this way? The project executes the SPring MVC Web App just fine and the Drools KIE test case runs perfectly in the same Maven project. Can't I just integrate them programmatically instead?
Many thanks in advance ... :-)
The offending file: application.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:kie="http://drools.org/schema/kie-spring"
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 http://drools.org/schema/kie-spring http://drools.org/schema/kie-spring.xsd">
<context:component-scan base-package="com.versaggi.springweb"/>
<kie:kmodule id="ksession-rules">
<kie:kbase name="rules" packages="rules">
</kie:kbase>
</kie:kmodule>
<bean id="kiePostProcessor" class="org.kie.spring.KModuleBeanFactoryPostProcessor" />
</beans>