I have this class.
#Service
public class ConcurrentService{
public Map<String, Object> createList(){
this.asynCall();
}
#Async("taskExecutor")
private Future<Map<String, Object>> asynCall(){
.....
return new AsyncResult<Map<String, Object>>(mapResultMap);
}
}
My spring config is:
<task:annotation-driven executor="taskExecutor" mode="aspectj" />
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="50" />
<property name="maxPoolSize" value="300" />
<property name="queueCapacity" value="30" />
</bean>
And My Mockito Unit test
#RunWith(MockitoJUnitRunner.class)
public class ConcurrentServiceTest{
#InjectMocks
private ConcurrentService concurrentService;
#Mock(name = "taskExecutor")
private ThreadPoolTaskExecutor taskExecutor;
#Test
public void test1(){
Assert.assertNotNull(concurrentService.createList();
}
}
If I run this I obtained java.lang.IllegalArgumentException: BeanFactory must be set on AnnotationAsyncExecutionAspect to access qualified executor 'taskExecutor' from the org.springframework.scheduling.aspectj.AbstractAsyncExecutionAspect.ajc$around$org_springframework_scheduling_aspectj_AbstractAsyncExecutionAspect
If I remove the qualifier in the annotation and just left #Async, this test run perfectly, but If I add the #Async("taskExecutor") the error comes again.
I believe Spring does not need to run as this is just Unit test, what can I do to disable aop in Mockito or what should I do to use the name "taskExecutor"
With mode="aspectj" in
<task:annotation-driven executor="taskExecutor" mode="aspectj" />
you are using Aspectj weaving, and you needs to use aspectj-maven-plugin to weave aspects in compile time. For using Spring's AOP default framework with proxies in runtime, change to
<task:annotation-driven executor="taskExecutor" />
Related
i want to test a class with a Datasource bean injected, but i don't know how to Mock the Bean Datasource(i dont' have the class but only bean configuration).
My class is like this:
public class Configurazione {
private DataSource dataSource;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
...
}
my beans:
<bean id="Configurazione" class="com.company.configurazione.Configurazione">
<property name="dataSource" ref="dataSourceMySql" />
</bean>
<bean name="dataSourceMySql"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="..." />
<property name="username" value="..." />
<property name="password" value="..." />
</bean>
how can i test the class Configurazione with mockito and inject the datasource bean?
i've no class DataSource to #mock in the test class Configurazione.
Usually for testing purposes additional Spring application context is created. And you can define beans differently there. For example you can use in-memory HSQL database as your datasource
<jdbc:embedded-database id="dataSource" type="HSQL" >
<jdbc:script location="scripts/ddl/sequences/*"/>
<jdbc:script location="scripts/ddl/tables/*"/>
<jdbc:script location="scripts/dml/*"/>
</jdbc:embedded-database>
To use this snippet of code as-is you need to add hsql dependency to your project and adjust paths to scripts (these scripts create and populate database schema used in your tests).
And you run your tests with that test application context
I have a spring bean that is created through factory-method and I also need to use #Transactional facility. So, when I create it as follows:
<bean id="myBean" class="pack.age.MyBean" factory-method="create">
<constructor-arg ref="someBean" />
</bean>
where
public class MyBean implements MyInterface{
private final SomeBean someBean;
public static MyInterface create(SomeBean someBean){
MyBean retVal = new MyBean(someBean);
//Create a thread and run it.
//Do some other job that doesn't suit for constructor
}
private MyBean(SomeBean someBean){
this.someBean = someBean;
}
}
Now, when I try to inject the bean into anothe bean:
public class MyAnotherBean{
private MyInterface myInterface;
public boid setMyInterface(MyInterface myInterface){
this.myInterface = myInterface;
}
}
declared as
<bean id="myAnotherBean" class="pack.age.MyAnotherBean">
<property name="myInterface" ref="myBean" />
</bean>
The actual myBean instance, not a proxy is injected. Since it's not a proxy, I can't use Spring #Transactional facility.
How can I inject a proxy when constructing an object through static factory-method?
In this case just enabling transaction annotation under the beans declaration should work:
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- (this dependency is defined somewhere else) -->
<property name="dataSource" ref="dataSource"/>
</bean>
But if not you can try enable the transaction declaratively:
<tx:advice id="txAdvice" transaction-manager="txManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true"/>
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- ensure that the above transactional advice runs for any execution
of an operation defined by the MyInterface interface -->
<aop:config>
<aop:pointcut id="myBeanOperation" expression="execution(* x.y.service.MyInterface.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="myBeanOperation"/>
</aop:config>
I am quite new to Spring and Activiti. I'm developing annotation based Spring web application with embedded Activiti engine. I have some services implemented, SubscriptionService is one of them. In one process I call that service as bean with:
activiti:expression="${subscriptionService.getContacts(publisherCode, contactType)}"
Service:
#Service
#Transactional
public class DBSubscriptionService implements SubscriptionService {
...
}
I have separated test module and web module. Test module loads context from activiti.cfg.xml with
#ContextConfiguration("classpath:activiti.cfg.xml")
and it is:
<bean id="processEngineConfiguration"
class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
<property name="databaseType" value="h2" />
<property name="databaseSchemaUpdate" value="true" />
<property name="jobExecutorActivate" value="false" />
<property name="history" value="full" />
<property name="mailServerPort" value="2025" />
</bean>
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<bean id="repositoryService" factory-bean="processEngine"
factory-method="getRepositoryService" />
<bean id="runtimeService" factory-bean="processEngine"
factory-method="getRuntimeService" />
<bean id="taskService" factory-bean="processEngine"
factory-method="getTaskService" />
<bean id="historyService" factory-bean="processEngine"
factory-method="getHistoryService" />
<bean id="managementService" factory-bean="processEngine"
factory-method="getManagementService" />
<bean id="identityService" factory-bean="processEngine"
factory-method="getIdentityService" />
<bean id="formService" factory-bean="processEngine"
factory-method="getFormService" />
<context:component-scan base-package="cz.muni.fi.cep" />
<context:annotation-config />
In test module, everything works fine. But in web module when it should call subscriptionService Bean it throws:
Unknown property used in expression: ${subscriptionService.getContacts(publisherCode, contactType)}
Caused by: org.activiti.engine.impl.javax.el.PropertyNotFoundException: Cannot resolve identifier 'subscriptionService'
at org.activiti.engine.impl.juel.AstIdentifier.eval(AstIdentifier.java:83)
at org.activiti.engine.impl.juel.AstMethod.invoke(AstMethod.java:79)
at org.activiti.engine.impl.juel.AstMethod.eval(AstMethod.java:75)
at org.activiti.engine.impl.juel.AstEval.eval(AstEval.java:50)
at org.activiti.engine.impl.juel.AstNode.getValue(AstNode.java:26)
at org.activiti.engine.impl.juel.TreeValueExpression.getValue(TreeValueExpression.java:114)
at org.activiti.engine.impl.delegate.ExpressionGetInvocation.invoke(ExpressionGetInvocation.java:33)
at org.activiti.engine.impl.delegate.DelegateInvocation.proceed(DelegateInvocation.java:37)
at org.activiti.engine.impl.delegate.DefaultDelegateInterceptor.handleInvocation(DefaultDelegateInterceptor.java:25)
at org.activiti.engine.impl.el.JuelExpression.getValue(JuelExpression.java:48)
... 363 more
So I understand problem is that Process engine does not use right application context, because subscription service is autowired to other classes just fine. But I don't know how to fix it.
Web module is purely annotation based:
#EnableAutoConfiguration
#Configuration
#EntityScan(basePackages = "cz.muni.fi.cep")
#ComponentScan(basePackages = "cz.muni.fi.cep")
public class App extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
...
}
And Activiti configuration:
#Configuration
public class ActivitiConfig {
#Bean
public ProcessEngine processEngine(ProcessEngineConfigurationImpl pec, ApplicationContext applicationContext) throws Exception {
ProcessEngineFactoryBean pe = new ProcessEngineFactoryBean();
pe.setProcessEngineConfiguration(pec);
pe.setApplicationContext(applicationContext);
return pe.getObject();
}
#Bean
public ProcessEngineConfigurationImpl getProcessEngineConfiguration(
DataSource dataSource,
PlatformTransactionManager transactionManager,
ApplicationContext context) {
SpringProcessEngineConfiguration pec = new SpringProcessEngineConfiguration();
pec.setDataSource(dataSource);
pec.setDatabaseSchemaUpdate("true");
pec.setJobExecutorActivate(true);
pec.setHistory("full");
pec.setMailServerPort(2025);
pec.setDatabaseType("mysql");
pec.setTransactionManager(transactionManager);
pec.setApplicationContext(context);
return pec;
}
#Bean
public RuntimeService getRuntimeService(ProcessEngine processEngine) {
return processEngine.getRuntimeService();
}
...
}
Also, maybe order of context creation has somethong to do with this.
Everything looks OK, I believe it might be something as simple as the subscription service not being scanned (does it belong to package cz.muni.fi.cep?), or Spring assigning another name to the subscription service bean (i.e. dbSubscriptionService or dBSubscriptionService instead of just subscriptionService).
Try replacing #Service in DBSubscriptionService class by #Service("subscriptionService") and it should work.
When I try to load a resource, it never gets loaded and instead comes back as null. My code is as follows:
Controller.java
#Controller
#Path("/users")
public class UsersAPI {
#Resource(name = "dataLoaderList")
private List<DataLoader> dataLoaderList;
}
spring.xml
<context:component-scan base-package="com.my.package" />
<import resource="classpath:spring/commons.xml" />
<import resource="spring-dataloader.xml" />
<import resource="spring-security.xml" />
spring-dataloader.xml
<bean id="dataLoaderList"
class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
<ref bean="dataLoader1" />
<ref bean="dataLoader2" />
<ref bean="dataLoader3" />
</list>
</property>
</bean>
What could I be missing?
EDIT:
I tried loading the resource in a JUnit Test, and it worked. So I have no idea why it wouldn't work in my Controller.
junit
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:spring/spring.xml")
#ActiveProfiles("dev")
public class Test {
#Resource(name = "dataLoaderList")
private List<DataLoader> dataLoaderList;
}
I had to change #Controller annotation to #Component and that fixed my error. I have no idea why it worked.
This question already has answers here:
Howto get rid of <mvc:annotation-driven />?
(4 answers)
Closed 9 years ago.
What exactly would be an equivalent manual configuration to mvc:annotation-driven in spring mvc? Because my webapp implements RequestMappingHandlerMapping, I cannot use mvc:annotation-driven but have to configure this myself.
Specifically I'm wondering what configuration has to be included in order for the #Async annotation to work. I am not sure if it does atm. I'm starting a background task at startup which is supposed to run as long as the webapp is running and it seems to me that the whole server waits for this (never-ending) method to finish. The #Async-Method is in a worker-service which gets called by another service on #PostConstruct.
Here are the two classes:
#Service
public class ModuleDirectoryWatcher{
#Autowired
ModuleDirectoryWatcherWorker worker;
#PostConstruct
public void startWatching() {
worker.startWatching();
}
}
#Service
public class ModuleDirectoryWatcherWorker {
#Async
public void startWatching() {
createPluginDir();
initializeClassloader();
initializeWatcher();
watch();
}
}
The relevant part of my applicationContext.xml looks like this so far:
<bean name="handlerAdapter"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"</bean>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</list>
</property>
</bean>
<bean name="handlerMapping"
class="com.coderunner.caliope.module.api.impl.ModuleHandlerMapping">
</bean>
Now I feel silly... In order to work, #Async and #Scheduled need
<task:annotation-driven executor="myExecutor" scheduler="myScheduler" />
<task:executor id="myExecutor" pool-size="5" />
<task:scheduler id="myScheduler" pool-size="10" />
even if you don't use
Maybe it helps someone out there