Spring Batch- Write to two different file based on condition - spring-batch

I want to write data to two different files. If my condition is true then write to x file otherwise to y file.
Currently I have a flat file item writer that writes all the data to one file. I want to specify two different files and based on condition data should go to perticular file.
<beans:bean id="itemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter">
<beans:property name="resource">
<beans:bean class="org.springframework.core.io.FileSystemResource" scope="step">
<beans:constructor-arg value="${process.output.dir}/${output.file.name}_#{jobParameters['run.id']}.${output.file.extension}" type="java.lang.String" />
</beans:bean>
</beans:property>
<beans:property name="lineAggregator">
<beans:bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
<beans:property name="delimiter" value="|" />
<beans:property name="fieldExtractor">
<beans:bean class="com.abc.common.batch.item.file.transform.FormattingFieldExtractorDecorator">
<beans:property name="fieldExtractor">
<beans:bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor" >
<beans:property name="names" value="${output.field.names}" />
</beans:bean>
</beans:property>
<beans:property name="defaultDateFormat" value="yyyyMMdd" />
<beans:property name="defaultDecimalFormat" value="############0.00" />
</beans:bean>
</beans:property>
</beans:bean>
</beans:property>
<beans:property name="headerCallback">
<beans:bean class="com.abc.common.batch.item.file.HeaderWriter">
<beans:constructor-arg value="${output.column.names}" />
</beans:bean>
</beans:property>
<beans:property name="footerCallback">
<beans:bean class="com.abc.footer.ItemCountFooterCallback" >
<beans:constructor-arg name="count" ref="itemCount" />
</beans:bean>
</beans:property>
</beans:bean>

ClassifierCompositeItemWriter is the way to go. It uses a Classifier to classify items (this is where you would implement your condition) and multiple item writers (each one will write a specific "class" of items).
You can find an example here.
Hope this helps.

you can definitely do this , you can implement a custom item writer and then based on your conditions you can achieve the task of writing into different files.
But in this case - the condition and handling the file may hamper the performance of your application , you need to be careful with your implementation
Here I am just giving you the layout , you can write the implementation of writing in your file , first write the custom item writer -
https://www.programcreek.com/java-api-examples/index.php?api=org.springframework.batch.item.ItemWriter
And then implement a custom itemWriterListener - in which using the beforeWrite method - you can set a different resource
public class WriteListener implements ItemWriteListener{
#Autowire
ItemWrite writer;
public void beforeWrite(List items) {
condition 1 (){
writer.setResource(1)
}
condition 2 (){
writer.setResource(2)
}
}
public void onWriteError(Exception exception, List items) {
System.out.println("Error occurred when writing items!");
}
public void afterWrite(List items) {
}
}

Related

Target Table is not updated properly

I have used:
spring mvc-version:4.3.7 postgres:9.5 Tool:STS
I want to update my database. But after entry in the form , when I click submit button- it is shown:
Request processing failed; nested exception is
org.springframework.orm.hibernate5.HibernateOptimisticLockingFailureException:
Object of class [com.asha.farmvill.model.Division] with identifier
[0]: optimistic locking failed; nested exception is
org.hibernate.StaleObjectStateException: Row was updated or deleted by
another transaction (or unsaved-value mapping was incorrect) :
[com.asha.farmvill.model.Division#0]
this is my controller:
#RequestMapping("/edit/{id}")
public String editDivision(#PathVariable("id") int id, Model model) {
model.addAttribute("division", this.divisionService.getdivisionById(id));
return "editdivision";
}
#PostMapping(value="/updatedivision")
public String updateEmployee(#ModelAttribute("division")Division division, ModelMap model) {
this.divisionService.updatedivision(division);
return "divisionlist";
}
The DAO is given below:
public void updatedivision(Division p) {
Session session = this.sessionFactory.getCurrentSession();
session.update(p);
System.out.println("Division updated successfully, Division Details=" + p.getName());
}
This is my servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<beans:property name="driverClassName" value="org.postgresql.Driver" />
<beans:property name="url"
value="jdbc:postgresql://localhost:5432/firmvilldb" />
<beans:property name="username" value="postgres" />
<beans:property name="password" value="root" />
</beans:bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<beans:bean id="hibernate5AnnotatedSessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="annotatedClasses">
<beans:list>
<beans:value>com.asha.farmvill.model.Division</beans:value>
</beans:list>
</beans:property>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect
</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="divisionDao" class="com.asha.farmvill.dao.DivisionDaoImp">
<beans:property name="sessionFactory" ref="hibernate5AnnotatedSessionFactory" />
</beans:bean>
<beans:bean id="divisionService" class="com.asha.farmvill.service.DivisionServiceImp">
<beans:property name="divisionDao" ref="divisionDao"></beans:property>
</beans:bean>
<context:component-scan base-package="com.asha.farmvill" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<beans:bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="hibernate5AnnotatedSessionFactory" />
</beans:bean>
</beans:beans>
How can I solve the problem?
Add #Transactional annotation on top of the method like below.
#Transactional
public void updatedivision(Division p) {
Session session = this.sessionFactory.getCurrentSession();
session.update(p);
System.out.println("Division updated successfully, Division Details=" + p.getName());
}
Refer Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)

Spring Batch With Schedular

enter image description hereI am new to Spring Batch with Scheduler. Here my task is to read the data from one table and write it into another table.
I am randomly going through the blogs and different tutorials.
I don't know whether there is any direct approach read from database and write into database. I took this approach like
Job 1 : Reads the data from the db using JdbcCursorItemReader, writing the data into a txt file using FlatFileItemWriter.
Job 2: Read the data from the txt file using FlatFileItemReader, multiResourceItemReader and writing the data into another table using HibernateItemWriter.
I am using a scheduler and it is going to run the batch for every 20 sec.
In this approach for the first run it is working fine. For the second run(after 20 sec), I am updating the data in the database(base table) but it is not writing updated data into the file and database.
Here is my configuration & code`package com.cg.schedulers;
public class UserScheduler {
#Autowired
private JobLauncher launcher;
#Autowired
private Job userJob;
#Autowired
private Job userJob2;
private JobExecution execution1,execution2;
public void run() {
try {
execution1 = launcher.run(userJob, new JobParameters());
execution2 = launcher.run(userJob2, new JobParameters());
System.out.println("Execution status: " + execution1.getStatus());
System.out.println("Execution status: " + execution2.getStatus());
} catch (JobExecutionAlreadyRunningException e) {
e.printStackTrace();
} catch (JobRestartException e) {
e.printStackTrace();
} catch (JobInstanceAlreadyCompleteException e) {
e.printStackTrace();
} catch (JobParametersInvalidException e) {
e.printStackTrace();
}
}
}
Xml Configuration
<import resource="spring-batch1.xml" />
<import resource="springbatch-database.xml" />
<context:annotation-config/>
<context:component-scan base-package="com.cg"/>
<!-- Reading data from -->
<bean id="itemReader"
class="org.springframework.batch.item.database.JdbcCursorItemReader"
scope="step">
<property name="dataSource" ref="dataSource" />
<property name="sql" value="select UserId, UserName, Password from USER" />
<property name="rowMapper">
<bean class="com.cg.mapper.UserRowMapper" />
</property>
</bean>
<!-- ItemWriter writes a line into output flat file -->
<bean id="flatFileItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter"
scope="step">
<property name="resource" value="file:csv/User.txt" />
<property name="lineAggregator">
<!-- An Aggregator which converts an object into delimited list of strings -->
<bean
class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
<property name="delimiter" value="," />
<property name="fieldExtractor">
<!-- Extractor which returns the value of beans property through reflection -->
<bean
class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
<property name="names" value="userId, username, password" />
</bean>
</property>
</bean>
</property>
</bean>
<!-- ItemReader reads a complete line one by one from input file -->
<bean id="flatFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader"
scope="step">
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="fieldSetMapper">
<!-- Mapper which maps each individual items in a record to properties
in POJO -->
<bean class="com.cg.mapper.UserFieldSetMapper" />
</property>
<property name="lineTokenizer">
<!-- A tokenizer class to be used when items in input record are separated
by specific characters -->
<bean
class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="delimiter" value="," />
</bean>
</property>
</bean>
</property>
</bean>
<bean id="multiResourceItemReader"
class="org.springframework.batch.item.file.MultiResourceItemReader">
<property name="resources" value="classpath:csv/User.txt" />
<property name="delegate" ref="flatFileItemReader" />
</bean>
<!-- Optional JobExecutionListener to perform business logic before and
after the job -->
<bean id="jobListener" class="com.cg.support.UserItemListener" />
<!-- Optional ItemProcessor to perform business logic/filtering on the input
records -->
<bean id="itemProcessor1" class="com.cg.support.UserItemProcessor" />
<bean id="itemProcessor2" class="com.cg.support.UserItemProcessor2" />
<!-- ItemWriter which writes data to database -->
<bean id="databaseItemWriter"
class="org.springframework.batch.item.database.HibernateItemWriter">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- Actual Job -->
<batch:job id="userJob">
<batch:step id="step1">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="itemReader" writer="flatFileItemWriter"
processor="itemProcessor1" commit-interval="10" />
</batch:tasklet>
</batch:step>
<batch:listeners>
<batch:listener ref="jobListener" />
</batch:listeners>
</batch:job>
<batch:job id="userJob2">
<batch:step id="step2">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="multiResourceItemReader" writer="databaseItemWriter"
processor="itemProcessor2" commit-interval="10" />
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="myScheduler" class="com.cg.schedulers.UserScheduler"/>
<task:scheduled-tasks>
<task:scheduled ref="myScheduler" method="run" cron="*/20 * * * * *" />
</task:scheduled-tasks>
Please provide the direct approach if possible using hibernate.
[enter image description here][2]
Execution status: COMPLETED
Thanks,
Vamshi.

Spring-batch ignoring rows processed before encountering skippable Exception

Hi I am new to Spring batch and using version 3.0.4.RELEASE for my POC to process a very large flat file as below.
Running the batch in chunk processing mode.
A custom reader delegate with synchronized methods to run the
A custom processor which validates and tranforms the data.
The file format is as below.
COB_DATE HIERARCHY_NODE_ID HIERARCHY_LEVEL MEASURE CURRENCY VALUE
20151009 329715 COSTCENTER TOV_Position_60d USD 21848543.55
20151009 329715 COSTCENTER TOV_Position_90d USD 9040531.7
201510009 329715 COSTCENTER TOV_Ratio_30d 47.0069727152
20151009 329715 COSTCENTER TOV_Ratio_60d 20.2442137613
20151009 329715 COSTCENTER TOV_Ratio_90d 121.7425393354
20151009 329715 COSTCENTER TOV_Turnover_30d USD 259996659.00
I have a validation on the COB_DATE field, and in the processor I am throwing an ValidationException if the format is incorrect.
The problem is all the valid rows before the validation exception was thrown are skipped and unavailable for the writer. In this case row1 and row2.
Here is the job configuration
<beans:import resource="JobContext.xml" />
<!-- Starting point of the feed runner -->
<beans:bean id="feedJobRunner" class="com.ubs.risk.arisk.job.FeedJobRunner" >
<beans:constructor-arg name="jobLauncher" ref="jobLauncher"/>
<beans:constructor-arg name="job" ref="feedJob"/>
<beans:constructor-arg name="feedDao" ref="feedDao"/>
</beans:bean>
<beans:bean id="feedReader" class="com.ubs.risk.arisk.job.batch.FeedReaderDelegate" scope="step">
<beans:constructor-arg>
<beans:bean class="org.springframework.batch.item.file.FlatFileItemReader">
<beans:property name="resource" value="#{jobParameters['inputResource']}"/>
<beans:property name="linesToSkip" value="1"/>
<beans:property name="lineMapper">
<beans:bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<beans:property name="lineTokenizer">
<beans:bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<beans:property name="delimiter" >
<util:constant static-field="org.springframework.batch.item.file.transform.DelimitedLineTokenizer.DELIMITER_TAB" />
</beans:property>
<beans:property name="names" value="#{jobParameters['fieldNames']}"/>
<beans:property name="strict" value="false"/>
</beans:bean>
</beans:property>
<beans:property name="fieldSetMapper" >
<beans:bean class="com.ubs.risk.arisk.job.batch.FeedFieldSetMapper"/>
</beans:property>
</beans:bean>
</beans:property>
</beans:bean>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="feedProcessor" class="com.ubs.risk.arisk.job.batch.FeedRowProcessor" scope="step" >
<beans:constructor-arg name="feedDao" ref="feedDao" />
<beans:constructor-arg name="stepExecution" value="#{stepExecution}"/>
</beans:bean>
<beans:bean id="feedWriter" class="com.ubs.risk.arisk.job.batch.FeedWriter" scope="step">
<beans:constructor-arg name="dataSource" ref="dataSource" />
</beans:bean>
<job id="feedJob">
<step id="importFeedStep">
<tasklet task-executor="stepExecutor" throttle-limit="10">
<chunk reader="feedReader" processor="feedProcessor" writer="feedWriter" commit-interval="300" skip-limit="100" >
<skippable-exception-classes>
<include class="com.ubs.risk.arisk.job.batch.exception.FeedValidationException"/>
</skippable-exception-classes>
<listeners>
<listener>
<beans:bean class="com.ubs.risk.arisk.job.batch.listener.FeedSkipListener">
<beans:property name="feedDao" ref="feedDao"/>
</beans:bean>
</listener>
</listeners>
</chunk>
</tasklet>
<listeners>
<listener >
<beans:bean id="feedStepListener" class="com.ubs.risk.arisk.job.batch.listener.FeedStepListener">
<beans:constructor-arg name="feedDao" ref="feedDao" />
</beans:bean>
</listener>
</listeners>
</step>
<listeners>
<listener>
<beans:bean id="feedJobListener" class="com.ubs.risk.arisk.job.batch.listener.FeedJobListener">
<beans:constructor-arg name="processDao">
<beans:bean class="com.ubs.risk.arisk.job.batch.dao.JdbcProcessDao">
<beans:property name="dataSource" ref="dataSource"/>
</beans:bean>
</beans:constructor-arg>
</beans:bean>
</listener>
</listeners>
<validator ref="jobParamValidator"/>
</job>
<beans:bean id="stepExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor" />
<beans:bean id="jobParamValidator" class="com.ubs.risk.arisk.job.batch.validation.JobParameterValidator"/>
Thanks in advance for any suggestions.

How to allow null date in Spring 3 MVC

I've defined a global formatter for date bindings:
<annotation-driven conversion-service="conversionService" />
<beans:bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<beans:property name="converters">
<beans:list>
...
</beans:list>
</beans:property>
<beans:property name="formatters">
<beans:set>
<beans:bean id="dateFormatter"
class="org.springframework.format.datetime.DateFormatter">
<beans:constructor-arg><beans:value>dd/MM/yyyy</beans:value></beans:constructor-arg>
</beans:bean>
</beans:set>
</beans:property>
</beans:bean>
This is working fine but now I also need that a particular date field can be left blank. How can I configure the formatter (or this very field) to accept null value?
Thanks! :)
You can do this by set lenient in false for DateFormatter
<mvc:annotation-driven conversion-service="conversionService"/>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<set>
<bean class="org.springframework.format.datetime.DateFormatter">
<constructor-arg>
<value>dd/MM/yyyy</value>
</constructor-arg>
<property name="lenient" value="false"/>
</bean>
</set>
</property>
</bean>

Spring security ACL, #Secured annotations

I currently running into trouble with spring security, I have been following the two last tutorials referenced on the spring security article page
Methods secured with the org.springframework.security.access.annotation.Secured don't seem to trigger any Spring Security logic.
This is my test file:
public class AclServiceTest {
#Autowired
PersonDataOnDemand pdod;
#Autowired
MyAclService aclService;
UserDetailsService uds = new MyUserDetailsService();
#Test
public void testWriteResourceAnnotation(){
Person p0 = pdod.getSpecificPerson(0);
Person p1 = pdod.getSpecificPerson(1);
Assert.isTrue(!p0.getId().equals(p1.getId()));
Resource r = new Resource(p0.getSite(), p0, p0.getPrivateFolder());
authenticatePerson(p0);
securedWriteResource(r);
authenticatePerson(p1);
try{
securedWriteResource(r);
fail();
} catch(Exception e){
}
}
#Secured("ACL_RESOURCE_WRITE")
public void securedWriteResource(Resource r){
return;
}
private void authenticatePerson(Person p){
UserDetails ud = uds.loadUserByUsername(p.getEmail());
SecurityContextHolder.getContext().setAuthentication(new RunAsUserToken("user-"+p.getId(), ud, p.getPassword(), ud.getAuthorities().toArray(new GrantedAuthority[0]), null));
}
}
If added the following lines to my web.xml
<!--Spring security filter-->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
And this is my security.xml configuration with the beans that are used:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="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-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd" >
<beans:bean id="ehCacheBasedAclCache" class="org.springframework.security.acls.domain.EhCacheBasedAclCache">
<beans:constructor-arg>
<beans:bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<beans:property name="cacheManager">
<beans:bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
</beans:property>
<beans:property name="cacheName" value="aclCache"/>
</beans:bean>
</beans:constructor-arg>
</beans:bean>
<!--
Partie gestion de la business logic ACL
-->
<global-method-security secured-annotations="enabled" access-decision-manager-ref="businessAccessDecisionManager"/>
<beans:bean id="businessAccessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
<beans:property name="allowIfAllAbstainDecisions" value="false"/>
<beans:property name="decisionVoters">
<beans:list>
<beans:ref local="roleVoter"/>
<beans:ref local="aclResourceReadVoter"/>
<beans:ref local="aclResourceWriteVoter"/>
<beans:ref local="aclResourceDeleteVoter"/>
<beans:ref local="aclResourceAdminVoter"/>
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>
<beans:bean id="aclResourceReadVoter" class="org.springframework.security.acls.AclEntryVoter">
<beans:constructor-arg ref="jdbcMutableAclService"/>
<beans:constructor-arg value="ACL_RESOURCE_READ"/>
<beans:constructor-arg>
<beans:list>
<beans:ref local="administrationPermission"/>
<beans:ref local="readPermission"/>
</beans:list>
</beans:constructor-arg>
<beans:property name="processDomainObjectClass" value="myapp.models.Resource"/>
<beans:property name="internalMethod" value="getRootFolder"/>
</beans:bean>
<beans:bean id="aclResourceWriteVoter" class="org.springframework.security.acls.AclEntryVoter">
<beans:constructor-arg ref="jdbcMutableAclService"/>
<beans:constructor-arg value="ACL_RESOURCE_WRITE"/>
<beans:constructor-arg>
<beans:list>
<beans:ref local="administrationPermission"/>
<beans:ref local="writePermission"/>
</beans:list>
</beans:constructor-arg>
<beans:property name="processDomainObjectClass" value="myapp.models.Resource"/>
<beans:property name="internalMethod" value="getRootFolder"/>
</beans:bean>
<beans:bean id="aclResourceDeleteVoter" class="org.springframework.security.acls.AclEntryVoter">
<beans:constructor-arg ref="jdbcMutableAclService"/>
<beans:constructor-arg value="ACL_RESOURCE_DELETE"/>
<beans:constructor-arg>
<beans:list>
<beans:ref local="administrationPermission"/>
<beans:ref local="deletePermission"/>
</beans:list>
</beans:constructor-arg>
<beans:property name="processDomainObjectClass" value="myapp.models.Resource"/>
<beans:property name="internalMethod" value="getRootFolder"/>
</beans:bean>
<beans:bean id="aclResourceAdminVoter" class="org.springframework.security.acls.AclEntryVoter">
<beans:constructor-arg ref="jdbcMutableAclService"/>
<beans:constructor-arg value="ACL_RESOURCE_ADMIN"/>
<beans:constructor-arg>
<beans:list>
<beans:ref local="administrationPermission"/>
</beans:list>
</beans:constructor-arg>
<beans:property name="processDomainObjectClass" value="myapp.models.Resource"/>
<beans:property name="internalMethod" value="getRootFolder"/>
</beans:bean>
<beans:bean id="administrationPermission" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<beans:property name="staticField" value="org.springframework.security.acls.domain.BasePermission.ADMINISTRATION"/>
</beans:bean>
<beans:bean id="readPermission" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<beans:property name="staticField" value="org.springframework.security.acls.domain.BasePermission.READ"/>
</beans:bean>
<beans:bean id="writePermission" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<beans:property name="staticField" value="org.springframework.security.acls.domain.BasePermission.WRITE"/>
</beans:bean>
<beans:bean id="deletePermission" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<beans:property name="staticField" value="org.springframework.security.acls.domain.BasePermission.DELETE"/>
</beans:bean>
The businessAccessDecisionManager bean is created and is given the voters, but the decide method is never called.
Anyone has an idea what's going wrong ?
Thank for your help.
I found out that <global-method-security ../> wasn't inserted in the right xml file. See here for more details. This file happens to be webmvc-config.xml in my Roo project.
That unfolded several problem, I need SpEL for ACL so I finally settled for this config:
<bean class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" id="methodExprHandler">
<property name="permissionEvaluator" ref="aclPermissionEvaluator" />
</bean>
<bean class="org.springframework.security.acls.AclPermissionEvaluator" id="aclPermissionEvaluator">
<constructor-arg ref="jdbcMutableAclService" />
</bean>
<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="methodExprHandler"/>
</security:global-method-security>
No voter logic for authorization.