Spring Application loads twice - java

I'm new to Spring and trying to get a example to work. But my application loads twice each time it starts. I think it could be a context problem because of my internet research and I have just one context.xml.
<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:annotation-config/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:environment.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="false"/>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:environment.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="false"/>
</bean>
<bean name="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper" />
<bean name="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="requestFactory" ref="requestFactory" />
</bean>
<bean name="requestFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<property name="connectTimeout" value="10000" />
<property name="readTimeout" value="10000" />
</bean>
<bean name="httpClient" class="org.apache.http.client.HttpClient" factory-bean="requestFactory" factory-method="getHttpClient"/>
<bean name="TraderApplication" class="net.mrmoor.TraderApplication"/>
<bean name="API" class="com.iggroup.api.API"/>
<bean name="LightStreamerComponent" class="com.iggroup.api.streaming.LightStreamerComponent"/>
</beans>
My code of the TraderApplication Class is:
... skipped imports ....
#SpringBootApplication
public class TraderApplication implements CommandLineRunner{
private static final Logger log = LoggerFactory.getLogger(TraderApplication.class);
#Autowired
protected ObjectMapper objectMapper;
#Autowired
private API api;
#Autowired
private LightStreamerComponent lightStreamerComponent = new LightStreamerComponent();
private AuthenticationResponseAndConversationContext authenticationContext = null;
private ArrayList<HandyTableListenerAdapter> listeners = new ArrayList<HandyTableListenerAdapter>();
public static void main(String args[]) {
SpringApplication.run(TraderApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
try {
if (args.length < 2) {
log.error("Usage:- Application identifier password apikey");
System.exit(-1);
}
String identifier = args[0];
String password = args[1];
String apiKey = args[2];
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/public-api-client-spring-context.xml");
TraderApplication app = (TraderApplication) applicationContext.getBean("TraderApplication");
app.run(identifier, password, apiKey);
} catch (Exception e) {
log.error("Unexpected error:", e);
}
}

You mention in your comments above you got this working by removing SpringApplication.run(TraderApplication.class, args); but this would be removing spring-boot from your application so I'm going to assume since your question has a tag of [spring-boot] that this is not what you wanted. So here is an alternative way that you can configure beans using your xml.
#ImportResource({"classpath*:public-api-client-spring-context.xml"}) //Proper way to import xml in Spring Boot
#SpringBootApplication
public class TraderApplication implements CommandLineRunner {
...code you had before goes here
#Autowired
TraderApplication app;
#Override
public void run(String... args) throws Exception {
.. your parsing logic here
app.run(identifier, password, apiKey); //Now uses the autowired instance
}
}
You didn't list your pom.xml or build.gradle but it's important to remember that components you have registered in your context xml may be automatically configured in Spring Boot and you may not need to register them yourself in your xml.(Depending on which items you have starters for in your build file)

Related

Spring #Scheduled does not work appropriate

I have a method that should run at some delay, make request to api and add the new photo to database. So, addPhoto is working fine. It can print some info, make a request, but doesn't add the photo. I checked the database and there are only one photo, that i added manually.
#Component("restBean")
#Service
public class RestService {
private static final String url1 = "https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?sol=1324&camera=fhaz&api_key=DEMO_KEY";
private PhotoDao photoDao;
#Autowired
public void setPhotoDao(PhotoDao photoDao) {
this.photoDao = photoDao;
}
#Scheduled(fixedRate = 5000)
public void addPhoto() {
System.out.println("TIME HAS COME");
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Response> response = restTemplate
.getForEntity(url1,
Response.class);
Photo[] photos = response.getBody().getPhotos();
this.photoDao.save(photos[0]);
}
}
I have tested this method and all works except the last string. I checked that i get the response and can get the object from it.
this.photoDao.save(photos[0]);
That's my DAO class
#Repository
public class PhotoDaoImpl implements PhotoDao {
private static final Logger logger = LoggerFactory.getLogger(PhotoDaoImpl.class);
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#Override
public void save(Photo photo) {
Session session = this.sessionFactory.getCurrentSession();
session.persist(photo);
logger.info("Photo successfully saved. Photo details: {}", photo);
}
#Override
public Photo findOne(int id) {
Session session = this.sessionFactory.getCurrentSession();
Photo photo = (Photo) session.load(Photo.class, new Integer(id));
logger.info("Photo successfully loaded. Photo details: {}", photo);
return photo;
}
#Override
#SuppressWarnings("unchecked")
public List<Photo> getAll() {
Session session = this.sessionFactory.getCurrentSession();
That's my spring xml configuration
<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"
xmlns:mvc="http://www.springframework.org/schema/mvc" 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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<!-- This helps in mapping the logical view names to directly view files under a certain pre-configured directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- Database Information -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/DayDatabase"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan">
<list>
<value>net.yan.model</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- It register the beans in context and scan the annotations inside beans and activate them -->
<context:component-scan base-package="net.yan"/>
<!-- This allow for dispatching requests to Controllers -->
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<!-- PhotoDao and PhotoService beans -->
<bean id="photoDao" class="net.yan.dao.PhotoDaoImpl">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
</bean>
<bean id="photoService" class="net.yan.service.PhotoServiceImpl">
<property name="photoDao" ref="photoDao"/>
</bean>
<bean id="restService" class="net.yan.service.RestService">
<property name="photoDao" ref="photoDao"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
</bean>
<task:scheduled-tasks scheduler="myScheduler">
<task:scheduled ref="restBean" method="addPhoto" fixed-delay="5000"/>
</task:scheduled-tasks>
<task:scheduler id="myScheduler"/>
UPD: To be clear, i have another method, that make request and add to database. It's in the same class that doesn't work.
#EventListener(ContextRefreshedEvent.class)
#Transactional
public void contextRefreshedEvent() {
if (this.photoDao.checkDataBase()) {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Response> response = restTemplate
.getForEntity(url,
Response.class);
Photo[] photos = response.getBody().getPhotos();
this.photoDao.save(photos[0]);
}
}
UPD2: There's link to full project https://github.com/Kabowyad/Test-Project/tree/api-test/src/main/java/net/yan/service

Hibernate JPA interceptor doesn't get call

The setup I have an old project that is stuck to jdk 1.5, thus spring and hibernate versions are also the maximum possible to support this version of java. Hibernate is 3.3.2.GA and spring is 3.1.1.RELEASE. Setup is the following:
<persistence-unit name="myUnit" transaction-type="RESOURCE_LOCAL">
<mapping-file>persistence-query.xml</mapping-file>
...
<properties>
<property name="hibernate.max_fetch_depth" value="3" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
<property name="hibernate.ejb.interceptor" value="com.myproj.common.dao.AuditInterceptor"/>
</properties>
</persistence-unit>
application context:
<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:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
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/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:component-scan base-package="..."/>
<tx:annotation-driven transaction-manager="transactionManager" />
<aop:aspectj-autoproxy/>
<bean id="applicationContextProvder" class="com.myproj.common.utils.ApplicationContextProvider"/>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:persistence.xml" />
<property name="persistenceUnitName" value="myUnit" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="jpaDialect" ref="jpaDialect" />
</bean>
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="ORACLE" />
<property name="showSql" value="true" />
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
<!-- Local transaction management -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
<property name="jpaDialect" ref="jpaDialect" />
</bean>
and my interceptor:
#Component
public class AuditInterceptor extends EmptyInterceptor {
private static final long serialVersionUID = 98658932451L;
#Autowired
private JdbcTemplate jdbcTemplate;
public void afterTransactionBegin(Transaction tx) {
if (user != null) {
jdbcTemplate.execute("call ah_audit_pkg.SetAudit('test')");
super.afterTransactionBegin(tx);
}
}
}
I run a junit to test that interceptor is getting called and it is not. In debug mode, I am able to see this:
Any help is appreciated! Why my intercetprot is not getting called.
Edit:
I also tried the interceptor to override the afterTransactionBegin but it didn't help.
I ended up with the following solution:
I have my entityt that extends from a superclass mapped entity:
#Entity
#Table(name = "my_table")
public class MyTable extends AuditInfo
The AuditInfo entity has the following mapping:
#MappedSuperclass
public abstract class AuditInfo implements Serializable {
...
#PrePersist
void onCreate() throws SQLException {
//this empty method is needed for AOP to trigger the audit information insert before entity is stored
}
#PreUpdate
void onPersist() throws SQLException {
//this empty method is needed for AOP to trigger the audit information insert before entity is updated
}
#PreRemove
void onRemove() throws SQLException {
//this empty method is needed for AOP to trigger the audit information insert before entity is removed
}
}
And the Aspect class:
#Aspect
#Component
public class MyAspect {
#Before("execution(* com.mypackage.entities.AuditInfo.on*(..))")
public void setAuditHistory(JoinPoint jp){
final AuditInfo info = ((AuditInfo)jp.getThis());
JdbcTemplate jdbcTemplate = ApplicationContextProvider.getApplicationContext().getBean(JdbcTemplate.class);
jdbcTemplate.execute(new CallableStatementCreator() {
public CallableStatement createCallableStatement(Connection conn) throws SQLException {
CallableStatement stmt = conn.prepareCall("begin ah_audit_pkg.SetAudit(?,?); end;");
stmt.setString(1, info.getAuditUser());
if(info.getAuditLocation() != null && info.getAuditLocation().trim().length() !=0) {
stmt.setString(2, info.getAuditLocation());
} else {
stmt.setString(2, info.getAuditUser());
}
return stmt;
}
}, new CallableStatementCallback<Object>() {
public Object doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {
return cs.executeUpdate();
}
});
}
}
It is to be noted that the Spring beans are extracted from the context and not autowired - this is because AOP is a singleton class in spring implementation, and none of the autowired beans will be ever instantiated even if they are available in the context. So I had to manually retrieve them for later usage.

Transaction not active in child method of ApplicationContext

I can only get an active programmatic transaction in my spring (3.0.5) jdbc application, running on Oracle 11.2,
when the txAdvice points to the actual method (mainTest()) called from the application context (example "AAA" below).
If the txAdvice points to a child method (transactionTest()) of mainTest() (example "BBB" below) then I no longer have an active transaction.
Relevant code:
public class MainDS {
public static Controller cont;
public static void main(String[] args) {
String [] configList ={"spring.xml"};
ApplicationContext ctx = new ClassPathXmlApplicationContext(configList);
cont = (Controller)ctx.getBean("controller");
cont.mainTest();
}
}
public class Controller {
private JdbcTemplate jdbcTemplate;
public void mainTest()
{
transactionTest();
// MainDS.cont.transactionTest(); // also does not work
}
public void transactionTest(){
try {
// This prints "Transaction active = true" for AAA but "Transaction active = false" for BBB
System.out.println("Transaction active = " + TransactionSynchronizationManager.isActualTransactionActive() );
} catch (SQLException e) {
e.printStackTrace();
}
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
and my spring.xml file is:
<?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:tx="http://www.springframework.org/schema/tx"
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/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="controller" class="Controller">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="main*" propagation="REQUIRED" /> <!-- AAA -->
<tx:method name="transaction*" propagation="REQUIRED" /> <!-- or BBB -->
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="myMethods" expression="execution(* *..Controller.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="myMethods" />
</aop:config>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataConfigPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="searchSystemEnvironment" value="true" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="initialSize" value="2" />
<property name="maxActive" value="2" />
<property name="url" value="my connection details" />
<property name="username" value="xxx" />
<property name="password" value="xxx" />
</bean>
</beans>
How do I get an active transaction for option BBB.
Any ideas very welcome.
Regards
DS
"BBB" case: the "mainTest()" method calls directly the "transactionTest()" method, omitting the aspect.
If you want to invoke the dynamically created proxy of the "transactionTest()" method, I suppose, you could do it through self bean reference (injected). Also as far as I remember, the spring manual used to suggest to call such methods via interface references (again using injected interface references).
Note: this is a really bad design! Implementation example (per request):
<bean id="controller" class="test.Controller">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
<property name="instance" ref="controller" />
</bean>
public class Controller {
private JdbcTemplate jdbcTemplate;
private Controller instance;
public void mainTest() {
instance.transactionTest();
}
public void transactionTest() {
System.out.println("Transaction active = " + TransactionSynchronizationManager.isActualTransactionActive() );
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public Controller getInstance() {
return instance;
}
public void setInstance(Controller instance) {
this.instance = instance;
}
}
Transaction active = true
This behaviour is well documented in the spring manual (I recall it in the Aspects section), so you should definitely read it: http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/aop.html section 9.6.1
More over, this question has already been covered here: One Service method invoke inner multiple method for Spring transaction

spring3 - application context - bean property name and reference - null pointer exception

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"/>

Struts 2, Spring Plugin + Shiro integration: Autowiring issue

I have an issue with Struts2(2.3.15.1) Spring plugin. I use Shiro for security, and configure it with Annotations. The code looks like this:
public class Order2Action extends BaseAction {
#Autowired private UserDAO userDAO;
private static final Logger log = LoggerFactory.getLogger(Order2Action.class);
#Action(value = "list2",
results = {#Result(name = SUCCESS, location = "list.jsp")}
)
#RequiresRoles(ROLE_DATA_OPERATOR)
public String showOrderList() throws InterruptedException {
log.info("UserDAOImpl {}", userDAO);
return SUCCESS;
}
}
In this case UserDAO is not injected to Action. But if I comment out the string "#RequiresRoles(ROLE_DATA_OPERATOR)" - UserDAO is injected to Action.
What could be the problem here?
My ApplicationContext conf looks like this:
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- enable processing of annotations such as #Autowired and #Configuration -->
<context:annotation-config/>
<context:component-scan base-package="ee"/>
<bean id="makuDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
...
</bean>
<!--Shiro security configuration -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/maku/auth/login"/>
<property name="unauthorizedUrl" value="/maku/auth/unauthenticated"/>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="cacheManager" ref="shiroCacheMan"/>
<property name="realm" ref="jdbcRealm"/>
</bean>
<bean id="jdbcRealm" class="org.apache.shiro.realm.jdbc.JdbcRealm">
<property name="dataSource" ref="makuDataSource"/>
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.PasswordMatcher"/>
</property>
</bean>
<bean name="shiroCacheMan" class="org.apache.shiro.cache.ehcache.EhCacheManager"/>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- Enable Shiro Annotations for Spring-configured beans. Only run after -->
<!-- the lifecycleBeanProcessor has run: -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
</beans>
UserDAO:
public interface UserDAO {
User getByUsername(String username);
}
#Repository
public class UserDAOImpl extends AbstractJDBCDAO implements UserDAO {
#Override
public User getByUsername(String username){
return makuTmpl.queryForObject("select id, username, fullname from users where username=?",
new RowMapper<User>() {
#Override
public User mapRow(ResultSet rs, int i) throws SQLException {
User u = new User();
u.setId(rs.getLong( 1 ));
u.setUsername(rs.getString(2));
u.setFullname(rs.getString(3));
return u;
}
}, username);
}
}

Categories