I built a CXF based soap web service and i was trying to add some security aspects using the WS-Security by following the steps of this tutorial.
I got the An error was discovered processing the header
Here are the important classes that add the security aspects to the soap ws
ServerPasswordCallback.java
import java.io.IOException;
import java.util.ResourceBundle;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.wss4j.common.ext.WSPasswordCallback;
public class ServerPasswordCallback implements CallbackHandler {
private static final String BUNDLE_LOCATION = "auth";
private static final String PASSWORD_PROPERTY_NAME = "auth.manager.password";
private static String password;
static {
final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_LOCATION);
password = bundle.getString(PASSWORD_PROPERTY_NAME);
}
#Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.setPassword(password);
}
}
ClientPasswordCallback.java
import java.io.IOException;
import java.util.ResourceBundle;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.wss4j.common.ext.WSPasswordCallback;
public class ClientPasswordCallback implements CallbackHandler {
private static final String BUNDLE_LOCATION = "auth";
private static final String PASSWORD_PROPERTY_NAME = "auth.manager.password";
private static String password;
static {
final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_LOCATION);
password = bundle.getString(PASSWORD_PROPERTY_NAME);
}
#Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.setPassword(password);
}
}
AuthServiceFactory.java
public final class AuthServiceFactory {
private static final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {
"com/company/auth/service/cxfClient.xml"
});
public AuthServiceFactory() {
}
public AuthService getService() {
return (AuthService) context.getBean("client");
}
}
auth_fr_FR
auth.manager.password=*****
cxfClient.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:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">
<bean id="proxyFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass" value="com.company.auth.service.AuthService" />
<property name="address"
value="http://localhost:8080/CXFSOAP-WebService/corporateAuth" />
<property name="inInterceptors">
<list>
<ref bean="logIn" />
</list>
</property>
<property name="outInterceptors">
<list>
<ref bean="logOut" />
<ref bean="saajOut" />
<ref bean="wss4jOut" />
</list>
</property>
</bean>
<bean id="client" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"
factory-bean="proxyFactory" factory-method="create" />
<bean id="logIn" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
<bean id="logOut" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
<bean id="saajOut" class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
<bean id="wss4jOut" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken" />
<entry key="user" value="ws-client" />
<entry key="passwordType" value="PasswordText" />
<entry key="passwordCallbackClass" value="com.company.auth.service.ClientPasswordCallback" />
</map>
</constructor-arg>
</bean>
</beans>
This file is for the client configuration
beans.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:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">
<jaxws:endpoint id="bookShelfService"
implementor="com.company.auth.service.AuthServiceImpl" address="/corporateAuth">
<jaxws:inInterceptors>
<bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"></bean>
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="passwordCallbackClass" value="com.company.auth.service.ServerPasswordCallback"></entry>
</map>
</constructor-arg>
</bean>
</jaxws:inInterceptors>
</jaxws:endpoint>
</beans>
This file is for the server configuration
Client.java
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import com.company.auth.bean.Employee;
import com.company.auth.service.AuthService;
public class Client {
public Client() {
super();
}
public static void main(String[] args) {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(AuthService.class);
factory.setAddress("http://localhost:8080/CXFSOAP-WebService/corporateAuth");
AuthService client = (AuthService) factory.create();
Employee employee = client.getEmployee("22222");
System.out.println("Server said: "+employee.getLastName()+" "+employee.getFirstName());
System.exit(0);
}
}
This is the client code that consumes the soap web service.
before adding the security configuration, the server was up and running and the client consumed the function of the soap api successfully but after the security modification, when the client attempts to use the web service function i get this error
org.apache.cxf.binding.soap.SoapFault: A security error was encountered when verifying the message
at org.apache.cxf.ws.security.wss4j.WSS4JUtils.createSoapFault(WSS4JUtils.java:216)
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:329)
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:184)
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:93)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.wss4j.common.ext.WSSecurityException: An
error was discovered processing the header
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.checkActions(WSS4JInInterceptor.java:370)
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:313)
... 34 more
I tried to manually add some wsse headers in the soap envelope but it didn't work.
I solved my problem by modifying the AuthServiceFactory.java class and the ClientPasswordCallback.java and the descriptor deployment file and i added a auth2_Fr_fr.properties file.
AuthServiceFactory.java
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.company.auth.bean.Employee;
public final class AuthServiceFactory {
private static final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "com/company/auth/service/cxfClient.xml" });
public AuthServiceFactory() {
}
public AuthService getService() {
return (AuthService) context.getBean("client");
}
public static void main(String[] args) {
AuthServiceFactory authSer = new AuthServiceFactory();
AuthService client = authSer.getService();
Employee employee = client.getEmployee("22222");
System.out.println("Server said: " + employee.getLastName() + " " + employee.getFirstName());
System.exit(0);
}
}
ClientPasswordCallback.java
import java.io.IOException;
import java.util.ResourceBundle;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.wss4j.common.ext.WSPasswordCallback;
public class ClientPasswordCallback implements CallbackHandler {
private static final String BUNDLE_LOCATION = "auth2";
private static final String PASSWORD_PROPERTY_NAME = "auth.manager.password";
private static String password;
static {
final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_LOCATION);
password = bundle.getString(PASSWORD_PROPERTY_NAME);
}
#Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.setPassword(password);
}
}
auth2_fr_Fr.properties
auth.manager.password=123456
Related
How to create timer task (cron-based) without it execution on each node i.e. one execution per one time point in timetable using Apache Ingite?
I have cluster that consists in 2 nodes and application (war) with timer-task. In non-cluster mode application works well. But it has inside timer-task (ie. start each 5 minutes), that works with shared resources.
I try to do it. But IngiteScheduler#scheduleLocal deploys and runs task on each node, if both application instance started (each application instance try to start same timer task).
I assume that ignite have mechanism for deploy task with id fot it...
Thanks.
Update 18.12.2018:
(thank #alamar for idea)
Below I show source and test for successful solutuion:
IgniteTimerTest.java:
package com.stackoverflow.question53780890.test;
import com.stackoverflow.question53780890.JobRunner;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteServices;
import org.apache.ignite.resources.SpringResource;
import org.apache.ignite.services.Service;
import org.apache.ignite.services.ServiceContext;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;
import java.io.Serializable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class IgniteTimerTest {
private static final ExecutorService ES = Executors.newFixedThreadPool(5);
#Test
public void test() throws Exception {
Future<ConfigurableApplicationContext> applicationContextFutureOne = ES.submit(() -> create(ConfigOne.class));
Future<ConfigurableApplicationContext> applicationContextFutureTwo = ES.submit(() -> create(ConfigTwo.class));
try (ConfigurableApplicationContext applicationContextOne = applicationContextFutureOne.get();
ConfigurableApplicationContext applicationContextTwo = applicationContextFutureTwo.get();) {
Ignite igniteOne = applicationContextOne.getBean(Ignite.class);
Ignite igniteTwo = applicationContextTwo.getBean(Ignite.class);
IgniteServices servicesOne = igniteOne.services();
IgniteServices servicesTwo = igniteTwo.services();
servicesOne.deployClusterSingleton(TestTimerRunner.class.getName(), new TestTimerRunner());
Thread.sleep(JobRunner.PERIOD * 3);
servicesTwo.deployClusterSingleton(TestTimerRunner.class.getName(), new TestTimerRunner());
Thread.sleep(JobRunner.PERIOD * 3);
applicationContextOne.close();
Thread.sleep(JobRunner.PERIOD * 3);
int countValue = JobRunner.getConterValue();
Assertions.assertTrue(9 <= countValue && countValue <= 11);
}
}
private ConfigurableApplicationContext create(Class mainClass) {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(mainClass);
return context;
}
class TestTimerRunner implements Serializable, Service {
#SpringResource(resourceClass = JobRunner.class)
private transient JobRunner jobRunner;
public TestTimerRunner() {
}
#Override
public void cancel(ServiceContext ctx) {
jobRunner.stop();
}
#Override
public void init(ServiceContext ctx) throws Exception {
}
#Override
public void execute(ServiceContext ctx) throws Exception {
jobRunner.start();
}
}
#Configuration
#ImportResource("classpath:common.xml")
public static class ConfigOne {
#Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
PropertySourcesPlaceholderConfigurer holder = new PropertySourcesPlaceholderConfigurer();
holder.setLocation(new ClassPathResource("one.properties"));
return holder;
}
}
#Configuration
#ImportResource("classpath:common.xml")
public static class ConfigTwo {
#Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
PropertySourcesPlaceholderConfigurer holder = new PropertySourcesPlaceholderConfigurer();
holder.setLocation(new ClassPathResource("two.properties"));
return holder;
}
}
}
JobRunner.java:
package com.stackoverflow.question53780890;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;
public class JobRunner implements Runnable {
public static final long PERIOD = 5_000;
private static AtomicInteger counter = new AtomicInteger();
#Autowired
private TaskScheduler taskScheduler;
private ScheduledFuture<?> job;
public static int getConterValue() {
return counter.get();
}
public void start() {
job = taskScheduler.scheduleAtFixedRate(this, PERIOD);
}
public void stop() {
job.cancel(true);
}
#Override
public void run() {
counter.incrementAndGet();
}
}
common.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:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:task="http://www.springframework.org/schema/task"
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/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="5"/>
<bean id="jobRunner" class="com.stackoverflow.question53780890.JobRunner"/>
<bean id="ignite" class="org.apache.ignite.IgniteSpringBean">
<property name="configuration" ref="igniteConfiguration"/>
</bean>
<bean id="igniteConfiguration" class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="igniteInstanceName" value="${igniteInstanceName}"/>
<property name="discoverySpi">
<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
<property name="ipFinder">
<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder"
p:addresses-ref="igniteNodesAddresses"/>
</property>
<property name="joinTimeout" value="20000"/>
<property name="localPort" value="${igniteLocalPort}"/>
<property name="localPortRange" value="1"/>
</bean>
</property>
<property name="communicationSpi">
<bean class="org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi">
<property name="localPort" value="${communicationSpiPort}"/>
</bean>
</property>
</bean>
<bean id="igniteNodesAddresses" class="org.springframework.util.StringUtils"
factory-method="commaDelimitedListToStringArray">
<constructor-arg type="java.lang.String" value="${igniteNodes}"/>
</bean>
</beans>
one.properties:
igniteLocalPort=47501
communicationSpiPort=47101
igniteNodes=localhost:47501,localhost:47502
igniteInstanceName=one
two.properties:
igniteLocalPort=47502
communicationSpiPort=47102
igniteNodes=localhost:47501,localhost:47502
igniteInstanceName=two
I think you could deploy a singleton service which will do scheduleLocal in its execute() and de-schedule in its cancel() method. This way it will be failed over to next node and properly re-schedule your tasks if current node leaves.
I made a WSS4JInInterceptor in a spring bean configuration file as follows
<?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:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">
<jaxws:endpoint id="book"
implementor="net.ma.soap.ws.endpoints.IBookEndPointImpl" address="/bookAuth">
<jaxws:inInterceptors>
<bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"></bean>
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="passwordCallbackClass" value="net.ma.soap.ws.service.ServerPasswordCallback"></entry>
</map>
</constructor-arg>
</bean>
</jaxws:inInterceptors>
</jaxws:endpoint>
</beans>
The ServerPasswordCallBack.java looks like the following
package net.ma.soap.ws.service;
import java.io.IOException;
import java.util.ResourceBundle;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.wss4j.common.ext.WSPasswordCallback;
public class ServerPasswordCallback implements CallbackHandler {
private static final String BUNDLE_LOCATION = "zuth";
private static final String PASSWORD_PROPERTY_NAME = "auth.manager.password";
private static String password;
static {
final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_LOCATION);
password = bundle.getString(PASSWORD_PROPERTY_NAME);
}
#Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.setPassword(password);
}
}
With the password verification, everything work just fine.
I'd like to know if there's any other way to enhance the handle(Callback) method to make it more sophisticated so it would be able to check more than just one parameter, for example if i can make it check an access token, it would be much more better.
the password property is defined in zuth_fr_FR.properties file as follows
auth.manager.password=najah
If you want to do some custom validation on your username and token (such as verify against a directoryservice using LDAP or something similar) you can write your own custom UsernameTokenValidator overriding verifyPlaintextPassword(UsernameToken usernameToken) of UsernameTokenValidator and hook it up to your WSS4JInInterceptor adding the following to your bean definition
<property name="wssConfig">
<ref bean="usernameTokenWssConfig"/>
</property>
And add the referenced class to your codebase:
#Component("usernameTokenWssConfig")
public class usernameTokenWssConfigWSSConfig {
public usernameTokenWssConfig() {
setValidator(WSSecurityEngine.USERNAME_TOKEN, new CustomUsernameTokenValidator());
setRequiredPasswordType(WSConstants.PASSWORD_TEXT);
}
}
Images of All Jars
This is the error image from the console.
I am trying to use the Jersey API along with Spring and Hibernate. However, defining session factory says NullPointerException. Can anybody help me to solve this? Added Full configuration with spring, hibernate and Jersey. Images of error and jar on top.
---------------------Dao Class:
package com.org.restservice.bo.user;
import java.util.List;
import com.org.restservice.common.Dao;
public interface AuthenticationDao extends Dao{
/*
* User Information List
*/
public List userInfo(AuthenticationVo authenticationVo) throws Exception;
}
---------------------DaoHibernate Class:
package com.org.restservice.bo.user;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.type.StringType;
import org.springframework.orm.hibernate3.HibernateCallback;
import com.org.restservice.common.BaseDaoHibernate;
import com.org.restservice.common.Constant;
public class AuthenticationDaoHibernate extends BaseDaoHibernate implements AuthenticationDao{
private Log log = LogFactory.getLog(AuthenticationDaoHibernate.class);
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
/*
* User Information List
*/
public List userInfo(AuthenticationVo authenticationVo) throws Exception{
System.out.println("Called Me>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
List<AuthenticationVo> findlist = new ArrayList<AuthenticationVo>();
final String sqlQuery = "SELECT USER_ID, ROLE_ID from STTM_USER_MASTER";
System.out.println("sqlQuery: "+sqlQuery);
List results = (List) getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
SQLQuery sq = session.createSQLQuery(sqlQuery);
sq.addScalar("USER_ID", StringType.INSTANCE);
sq.addScalar("ROLE_ID", StringType.INSTANCE);
return sq.list();
}
});
try {
if (results.size() > 0) {
Iterator itr = results.iterator();
while (itr.hasNext()) {
authenticationVo = new AuthenticationVo();
Object[] row = (Object[]) itr.next();
authenticationVo.setUser_id((String) row[0]);
authenticationVo.setRole_id((String) row[1]);
findlist.add(authenticationVo);
}
}
} catch (Exception e) {
System.out.println("FunctonVos error:" + e.getMessage());
}
System.out.println("Size of User List is: "
+ findlist.size());
System.out.println("Procedure call ended.");
return findlist;
}
}
---------------------Facade Class:
package com.org.restservice.bo.user;
import java.util.List;
import com.org.restservice.common.Facade;
public interface AuthenticationFacade extends Facade{
public void setAuthenticationDao(AuthenticationDao authenticationDao);
/*
* User Information List
*/
public List userInfo(AuthenticationVo authenticationVo) throws Exception;
}
---------------------FacadeImpl Class:
package com.org.restservice.bo.user;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.org.restservice.common.BaseFacade;
public class AuthenticationFacadeImpl extends BaseFacade implements AuthenticationFacade{
private static final Log log = LogFactory.getLog(AuthenticationFacadeImpl.class);
private AuthenticationDao authenticationDao;
public void setAuthenticationDao(AuthenticationDao authenticationDao) {
this.authenticationDao = authenticationDao;
}
/*
* User Information List
*/
public List userInfo(AuthenticationVo authenticationVo) throws Exception{
return authenticationDao.userInfo(authenticationVo);
}
}
---------------------Business Object Class:
package com.org.restservice.bo.user;
import com.org.restservice.common.BaseObject;
public class AuthenticationVo extends BaseObject{
private static final long serialVersionUID = 1L;
private String user_id;
private String role_id;
public AuthenticationVo(String user_id, String role_id) {
super();
this.user_id = user_id;
this.role_id = role_id;
}
public AuthenticationVo() {
super();
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public String getRole_id() {
return role_id;
}
public void setRole_id(String role_id) {
this.role_id = role_id;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((role_id == null) ? 0 : role_id.hashCode());
result = prime * result + ((user_id == null) ? 0 : user_id.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AuthenticationVo other = (AuthenticationVo) obj;
if (role_id == null) {
if (other.role_id != null)
return false;
} else if (!role_id.equals(other.role_id))
return false;
if (user_id == null) {
if (other.user_id != null)
return false;
} else if (!user_id.equals(other.user_id))
return false;
return true;
}
#Override
public String toString() {
return "AuthenticationVo [user_id=" + user_id + ", role_id=" + role_id + "]";
}
}
---------------------Action Class Declaration:
package com.org.restservice.portal.user;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.org.restservice.bo.user.AuthenticationFacade;
import com.org.restservice.bo.user.AuthenticationVo;
#Path("userService")
public class UserAction{
private final Log log = LogFactory.getLog(UserAction.class);
AuthenticationVo authenticationVo = new AuthenticationVo();
private AuthenticationFacade authenticationFacade = null;
private List<AuthenticationVo> listofUsers = new ArrayList<AuthenticationVo>();
public AuthenticationVo getAuthenticationVo() {
return authenticationVo;
}
public void setAuthenticationVo(AuthenticationVo authenticationVo) {
this.authenticationVo = authenticationVo;
}
public AuthenticationFacade getAuthenticationFacade() {
return authenticationFacade;
}
public void setAuthenticationFacade(AuthenticationFacade authenticationFacade) {
this.authenticationFacade = authenticationFacade;
}
public List<AuthenticationVo> getListofUsers() {
return listofUsers;
}
public void setListofUsers(List<AuthenticationVo> listofUsers) {
this.listofUsers = listofUsers;
}
#GET
#Produces( "application/json" )
public List<AuthenticationVo> customAction(){
if (log.isDebugEnabled()) {
log.debug("Entering into loadusers Method of AuthenticationAction: " +authenticationFacade);
}
try {
listofUsers = authenticationFacade.userInfo(authenticationVo);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(">>>>>>>>>>>>>>>>>>>>>" +listofUsers.size());
/*authenticationVo.setUser_id("1234");
authenticationVo.setRole_id("134352");
listofUsers.add(authenticationVo);*/
return listofUsers;
}
}
---------------------Spring Beans Declaration:
<!-- <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"> -->
<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:tx="http://www.springframework.org/schema/tx"
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-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- Database connection using jndi properties-->
<import resource="config/applicationContext-jndi.xml"/>
<import resource="config/applicationContext.xml"/>
<!-- List and Setup -->
<import resource="config/applicationContext-auth.xml"/>
</beans>
---------------------Application Context Declaration:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</prop>
</props>
</property>
</bean>
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<!-- Transaction template for Facade -->
<bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<!-- DAO bean -->
<!-- Generic DAO - can be used when doing standard CRUD -->
<bean id="dao" class="com.org.restservice.common.BaseDaoHibernate">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Generic Facade that can be used to do basic CRUD operations on any
objects -->
<bean id="facade" parent="txProxyTemplate">
<property name="target">
<bean class="com.org.restservice.common.BaseFacade">
<property name="Dao" ref="dao" />
</bean>
</property>
</bean>
</beans>
--------------------- Context Declaration:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- Transaction declarations for business services. -->
<bean id="authenticationFacade" parent="txProxyTemplate">
<property name="target">
<bean
class="com.org.restservice.bo.user.AuthenticationFacadeImpl">
<property name="authenticationDao">
<ref bean="authenticationDao" />
</property>
</bean>
</property>
</bean>
<!-- authenticationDao: Hibernate implementation -->
<bean id="authenticationDao"
class="com.org.restservice.bo.user.AuthenticationDaoHibernate">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
</beans>
---------------------Jndi Declaration:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<!-- author: Sarkar Zahir Ahamed <ahamed.sarkar#dbbl.com.bd> -->
<beans>
<!-- ========================= PERSISTENCE DEFINITIONS ========================= -->
<!-- JNDI DataSource for J2EE environments -->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:/comp/env/jndi/orcl</value>
</property>
</bean>
</beans>
---------------------Web XML Declaration:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>RestWebService</display-name>
<!-- Spring Listener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Jersey Servlet -->
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Register resources and providers -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.org.restservice</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<!-- loading Spring Context for registering beans with ApplicationContext -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/classes/SpringBeans.xml</param-value>
</context-param>
<!-- welcome file -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
My data is like this
UserId,UserData
1,data11
1,data12
2,data21
3,data31
The question is, how I can make the spring batch itemreader read multiple lines and map to object like
Map < userid, List < userdata > >
Steps to follow:
create a custom Item Writer class by implementing ItemWriter where we have implemented a logic to store User object in Map<String,List<String>> because a single user can have multiple associated data
package com.spring.batch.domain;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.batch.item.ItemWriter;
public class UserItemWriter implements ItemWriter<User> {
private static Map<String, List<String>> userMap = new HashMap<String, List<String>>();
public void write(List<? extends User> users) throws Exception {
for (User user : users) {
List<String> list = userMap.get(user.getUserId());
if (list == null) {
list = new ArrayList<String>();
}
list.add(user.getUserData());
userMap.put(user.getUserId(), list);
}
}
public static Map<String, List<String>> getUserMap() {
return userMap;
}
}
Plain User POJO class having two fieldsuserId anduserData
package com.spring.batch.domain;
public class User {
private String userId;
private String userData;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserData() {
return userData;
}
public void setUserData(String userData) {
this.userData = userData;
}
}
Main class to run the job
package com.spring.batch.main;
import java.util.List;
import java.util.Map;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.spring.batch.domain.UserItemWriter;
public class Main {
public static void main(String[] args) throws BeansException,
JobExecutionAlreadyRunningException, JobRestartException,
JobInstanceAlreadyCompleteException, JobParametersInvalidException {
ApplicationContext appContext = new ClassPathXmlApplicationContext(
"config/application-context.xml");
JobLauncher jobLauncher = (JobLauncher) appContext.getBean("jobLauncher");
jobLauncher.run(
(Job) appContext.getBean("job"),
new JobParametersBuilder().addString("input.file.name",
"file:src/main/resources/data/input.csv").toJobParameters());
Map<String,List<String>> userMap=UserItemWriter.getUserMap();
for (String userId : userMap.keySet()) {
System.out.println(userId + ":" + userMap.get(userId));
}
}
}
application-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<import resource="jobs.xml" />
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
<property name="transactionManager" ref="transactionManager" />
</bean>
<bean id="transactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
</beans>
jobs.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<job id="job" restartable="false"
xmlns="http://www.springframework.org/schema/batch">
<step id="step1">
<tasklet>
<chunk reader="csvItemReader" writer="userItemWriter"
commit-interval="2">
</chunk>
</tasklet>
</step>
</job>
<bean id="userItemWriter" class="com.spring.batch.domain.UserItemWriter"
scope="step" />
<bean id="csvItemReader" class="org.springframework.batch.item.file.FlatFileItemReader"
scope="step">
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean
class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names" value="userId,userData" />
</bean>
</property>
<property name="fieldSetMapper">
<bean
class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<property name="prototypeBeanName" value="user" />
</bean>
</property>
</bean>
</property>
<property name="linesToSkip" value="1" />
<property name="resource" value="#{jobParameters['input.file.name']}" />
</bean>
<bean id="user" class="com.spring.batch.domain.User" scope="prototype" />
</beans>
input.csv
UserId,UserData
1,data11
1,data12
2,data21
3,data31
Project structure screenshot (Maven)
All - In the Spring 3.0, in the applicationContext.xml .... are we supposed to have the bean property name and the reference value to be the same ? If I give a different value, it returns null object. But on giving the same value, it works. For my project, i am supposed to give different values for them. Kindly help. bye, HS
This works: (same values)
<bean id="MNCWIRAdminBaseAction" class="com.megasoft.wiradmin.web.action.WIRAdminBaseAction">
<property name="cacheDelegate">
<ref bean="cacheDelegate" />
</property>
</bean>
This doesn't work: (different values)
<bean id="MNCWIRAdminBaseAction" class="com.megasoft.wiradmin.web.action.WIRAdminBaseAction">
<property name="cacheDelegate">
<ref bean="MNCCacheDelegate" />
</property>
</bean>
bye, HS
My Full Code here:
WIRAdminBaseAction.java ---> my base action
AuthenticateAction.java ---> my java file that calls the bean here
applicationContext.xml --> system's applicationcontext file
applicationContext_MNC.xml ---> my applicationContext for a specific company ... this is getting loaded by my java file, which gets invoked by the web.xml file.
CacheDelegate.java
StatusDBDAO.java
PreXMLWebApplicationContext.java ----> loads my applicationContext file for the specific company.
****** applicationContext.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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<bean name="exceptionHandler" class="com.megasoft.wir.eStatement.web.interceptor.WIRExceptionHandlerInterceptor"/>
<bean name="security" class="com.megasoft.wir.eStatement.web.interceptor.SecurityInterceptor"/>
<bean name="permission" class="com.megasoft.wir.eStatement.web.interceptor.PermissionInterceptor"/>
<!-- AutoProxies -->
<bean name="loggingAutoProxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>base</value>
<value>exceptionHandler</value>
<value>security</value>
<value>permission</value>
</list>
</property>
</bean>
</beans>
****** applicationContext_MNC.xml ******
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="MNCWIRAdminBaseAction" class="com.megasoft.wiradmin.web.action.WIRAdminBaseAction">
<property name="cacheDelegate">
<ref bean="MNCCacheDelegate" />
</property>
</bean>
<bean id="MNCCacheDelegate" class="com.megasoft.wiradmin.delegate.CacheDelegate" >
<property name="statusDBDAO"><ref bean="MNCStatusDBDAO" /></property>
</bean>
<bean id="MNCStatusDBDAO" class="com.megasoft.wiradmin.dao.StatusDBDAO">
<property name="dataSource">
<ref bean="MNCAdminDataSource" />
</property>
</bean>
<!-- database configuration from property file -->
<bean id="MNCAdminDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close" lazy-init="default" autowire="default" dependency-check="default">
<property name="driverClass" value="${jdbc.driver}" ></property>
<property name="jdbcUrl" value="${admin.jdbc.url}" ></property>
<property name="user" value="${admin.jdbc.user}" ></property>
<property name="password" value="${admin.jdbc.password}" ></property>
<property name="initialPoolSize" value="3" ></property>
<property name="minPoolSize" value="3" ></property>
<property name="maxPoolSize" value="25" ></property>
<property name="acquireIncrement" value="1" ></property>
<property name="acquireRetryDelay" value="1000" ></property>
<property name="debugUnreturnedConnectionStackTraces" value="true" ></property>
<property name="maxIdleTime" value="300" ></property>
<property name="unreturnedConnectionTimeout" value="300000" ></property>
<property name="preferredTestQuery" value="SELECT COUNT(*) FROM LOCALE_CODE" ></property>
<property name="checkoutTimeout" value="300000" ></property>
<property name="idleConnectionTestPeriod" value="600000" ></property>
</bean>
<!-- this bean is set to map the constants which needs to be configured as per
the environment to the java constants file -->
<bean id="envConstantsConfigbean" class="com.megasoft.wiradmin.util.constants.Environm entConstantsSetter">
<property name="loginUrl" value="${login.url}"/>
<property name="logoutIR" value="${logout.from.image.retrieval}"/>
<property name="adminModuleUrl" value="${admin.url}"/>
<property name="adminUrlSym" value="${admin.url.sym}"/>
<property name="envProperty" value="${env.property}"/>
</bean>
</beans>
****** AuthenticateAction.java ******
package com.megasoft.wiradmin.web.action;
import java.net.UnknownHostException;
import java.sql.SQLException;
import org.bouncycastle.crypto.CryptoException;
import org.springframework.context.ApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.web.context.support.WebApplica tionContextUtils;
import com.megasoft.wiradmin.delegate.ICacheDelegate;
public class AuthenticateAction extends WIRAdminBaseAction {
private static final long serialVersionUID = 1L;
public String authenticate() throws UnknownHostException, CryptoException,
DataAccessException, SQLException{
/** This way of calling works...... This is not encouraged, as we should not use applicationContext always **/
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContex t(getServletRequest().getSession().getServletConte xt());
ICacheDelegate cacheAction = (ICacheDelegate) applicationContext.getBean("MNCCacheDelegate");
/** The below way of calling does NOT work .... returns null value.... Please help...
* I assume that, since I have extended the WIRAdminBaseAction, i should be able to call the getCacheDelegate directly
* and it should return my cacheDelegate object ...
* Again, Please note.....if I change my applicationContext_MNC.xml as below, the below way of calling works fine...
* but, i don't want to change my applicationContext_MNC.xml as below, due to some necessity.
*
<bean id="MNCWIRAdminBaseAction" class="com.megasoft.wiradmin.web.action.WIRAdminBaseAction">
<property name="cacheDelegate">
<ref bean="cacheDelegate" />
</property>
</bean>
*
<bean id="cacheDelegate" class="com.megasoft.wiradmin.delegate.CacheDelegate" >
<property name="statusDBDAO"><ref bean="MNCStatusDBDAO" /></property>
</bean>
*
... is it that the name and bean should have the same value.... ??? No Need to be.....Am i right ? Please advise.
*
* **/
getCacheDelegate().getActorAction(1); // this way of calling doesn't work and returns null value. please help.
return "success";
}
}
****** WIRAdminBaseAction.java ******
package com.megasoft.wiradmin.web.action;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.interceptor.ParameterAware;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;
import com.opensymphony.xwork2.config.entities.Parameteri zable;
import com.megasoft.wiradmin.delegate.ICacheDelegate;
public class WIRAdminBaseAction extends ActionSupport implements Preparable, ParameterAware, Parameterizable, SessionAware,RequestAware {
private HttpServletRequest request;
private static final long serialVersionUID = 1L;
private HttpServletResponse response;
private ICacheDelegate cacheDelegate;
private Map session;
private Map<String, String> params;
private Map parameters;
public void prepare() throws Exception {
}
public String execute() throws Exception {
return SUCCESS;
}
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public HttpServletRequest getServletRequest() {
return this.request;
}
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
public HttpServletResponse getServletResponse() {
return this.response;
}
public ICacheDelegate getCacheDelegate() {
return cacheDelegate;
}
public void setCacheDelegate(ICacheDelegate cacheDelegate) {
this.cacheDelegate = cacheDelegate;
}
public void addParam(final String key, final String value) {
this.params.put(key, value);
}
public Map getParams() {
return params;
}
public void setParams(final Map<String, String> params) {
this.params = params;
}
public Map getSession() {
return this.session;
}
public void setSession(final Map session) {
this.session = session;
}
public void setParameters(final Map param) {
this.parameters = param;
}
}
PreXMLWebApplicationContext.java **
package com.megasoft.wiradmin.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.support.XmlWebApplicationContext;
public class PreXMLWebApplicationContext extends XmlWebApplicationContext {
/**
* This initializes the Logger.
*/
private static Log logger = LogFactory.getLog(PreXMLWebApplicationContext.class);
protected String[] getDefaultConfigLocations() {
String environment = System.getProperty("envProperty");
String webirConfig = System.getProperty("webirConfig");
String fi = System.getProperty("FI");
String preHostConfiguration =null;
logger.info("The environment is "+environment);
logger.info("The webirConfig is "+webirConfig);
logger.info("The fi is "+fi);
if(environment != null && webirConfig != null && fi != null) {
preHostConfiguration = DEFAULT_CONFIG_LOCATION_PREFIX +
"classes/applicationContext" + "_" + fi.toUpperCase() +
DEFAULT_CONFIG_LOCATION_SUFFIX;
}
return new String[]{DEFAULT_CONFIG_LOCATION, preHostConfiguration};
}
/**
* This is close API.
*
* #see org.springframework.context.support.AbstractApplicationContext
* #close()
*/
public void close() {
this.doClose();
logger.info("Login-->into the closed");
}
}
<property name="userDelegate" ref="userDelegate" />
name is the field name in your class. When name is userDelegate, it means that WIRAdminBaseAction has a field named userDelegate (and probably a setter setUserDelegate())
ref is the bean name you want to set this field to. In your example, you should have another bean, named userDelegate or bmoUserDelegate which should be set as userDelegate in WIRAdminBaseAction.
So if you want to use the second configuration:
You just need to create a bean with id bmoUserDelegate:
<bean id="bmoUserDelegate" class="mypackage.BmoUserDelegateClass"/>