springmvc using excel template to export - spring

The code works well but when I setUrl to use my template in Excel, I get this error:
ApplicationObjectSupport instance [key.kotori.sms.utils.reports.StockReportsExcel: unnamed] does not run in an ApplicationContext'.
public class StockReportsExcel extends AbstractExcelView {
private StockReports reports;
public StockReportsExcel(StockReports reports) {
this.reports = reports;
//super.setUrl("report/stock.xls");
}
#Override
protected void buildExcelDocument(
Map<String, Object> model,
HSSFWorkbook workbook,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
workbook.createSheet().createRow(0).createCell(0).setCellValue("kotori");
RequestEncoding.encoding(request, response, "test.xls");
response.setContentType("application/vnd.ms-excel");
}
}
Controller
#RequestMapping("/excel.do")
public View excel(Params params) {
StockReports reports = this.stockReportService.reports(params);
StockReportsExcel excel = new StockReportsExcel(reports);
return excel;
}
I didn't set any ViewResolver in applicationContext.xml. Is there anything I'm missing in appicationContext.xml?
Here is the applicationContext.xml file.
<context:component-scan base-package="key.kotori.sms"></context:component-scan>
<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/sms"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mappingDirectoryLocations">
<list>
<value>classpath:key/kotori/sms/entity</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.format_sql=true
</value>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:advice id="txAdivce" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get" read-only="true" />
<tx:method name="list*" read-only="true" />
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="txAdivce" pointcut="execution(* key.kotori.sms.service.*.*(..))" />
</aop:config>

Related

Transaction is not being rollbacked in spring

While issuing two inserts, if second one is failed the transaction should be rollback but this is not happening in my case, following are the details of configuration!
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.xyz.model.Merchant</value>
....
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="modify*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="allServices"
expression="execution(*
com.xyz.services.DemoApiServiceImpl.saveEmployee(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="allServices"/>
</aop:config>
<aop:aspectj-autoproxy/>
and these are the code details;
#Service
#Transactional
public class DemoApiServiceImpl implements DemoApiService {
#Override
//#Transactional( propagation = Propagation.REQUIRED, rollbackFor = Exception.class )
public boolean saveEmployee(Employee employee) throws Exception {
Boolean flag = Boolean.FALSE;
flag = demoApiDao.saveOrUpdateEmployee(employee);
if(flag)
//generating exception so that above insert should rollback!
throw new Exception("ok");
if(!CollectionUtils.isEmpty(employee.getUsers())) {
Users user = (Users) employee.getUsers().toArray()[0];
//sendEmail(user,EmailType.USER_SIGN_UP.name(),Constants.MAIL_SUBJECT_ACTIVATION_LINK);
UsersDto usersDto = new UsersDto();
usersDto.setActivationCode(user.getActivationCode());
String emailText = Utils.createEmailText(usersDto, EmailType.USER_SIGN_UP.name());
Utils.sendEmail(user.getUsername(), Constants.FROM_EMAIL, Constants.MAIL_SUBJECT_ACTIVATION_LINK, emailText);
}
return flag;
}
}
unfortunately the transaction is not being rollbacked, I have generated exception manually to reverse the transaction.
Any help in this regards?
TA.

Bean property 'entityManager' is not writable or has an invalid setter method (using Spring and Hibernate)

Spring and hibernate are both new tools for me and I struggle a bit using both at the same time.
spring.xml :
<bean id="my.supervisionFramesProcess" class="supervision.frames.SupervisionFramesProcess"
init-method="startup" destroy-method="shutdown">
<property name="SupervisionDAO">
<bean class="supervision.dao.jpa.JpaSupervisionDao">
<property name="entityManager" ref="my.entity-manager-factory" />
</bean>
</property>
</bean>
<bean id="my.dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://XXXX/supervision?autoReconnect=true" />
<property name="username" value="***" />
<property name="password" value="***" />
<property name="maxIdle" value="5" />
<property name="maxActive" value="100" />
<property name="maxWait" value="30000" />
<property name="testOnBorrow" value="true" />
<property name="validationQuery" value="SELECT 1" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"></bean>
<bean id="my.entity-manager-factory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml" />
<property name="dataSource" ref="my.dataSource" />
<property name="persistenceUnitName" value="SUPERVISION-1.0" />
</bean>
JpaSupervisionDao.xml :
#PersistenceContext(unitName = "SUPERVISION-1.0")
private EntityManager entityManager;
public JpaSupervisionDao() {
if (logger.isDebugEnabled())
logger.debug("New instance DAO : " + this);
}
protected void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
protected EntityManager getEntityManager() {
return entityManager;
}
#Override
public SupervisionDbObject selectSupervisionDbObject(SupervisionDbObject supervision) {
Query query = getEntityManager().createQuery(SELECT_SUPERVISION);
}
persistence.xml :
<persistence-unit name="SUPERVISION-1.0">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>supervision.dao.SupervisionDbObject</class>
</persistence-unit>
Using JDBC, my DataSource can be instanciated and is fully working but using Hibernate and the entityManager, i only get an error :
Bean property 'entityManager' is not writable or has an invalid setter method.
I have tried to use the EntityManagerFactory object instead but the same error occurs.
Can someone help me out ?
The addition of the <context:annotation-config/> fixed my issue thanks to M. Deinum's answer.
If this can help someone else, I also had an issue with an import, I was importing
org.hibernate.annotations.Entity instead of javax.persistence.Entity.

Choose between muliple transaction managers at runtime

I have 2 clients using same Spring based REST Application deployed in tomcat. Depending on client I need to choose between data sources and transaction manager. How do I choose at runtime, which transaction manager to use?
<bean id="First_dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="url" value="${First_jdbc.url}" />
<property name="driverClassName" value="${First_jdbc.driverClassName}" />
<property name="username" value="${First_jdbc.username}" />
<property name="password" value="${First_jdbc.password}" />
<property name="removeAbandoned" value="true" />
<property name="initialSize" value="20" />
<property name="maxActive" value="30" />
<!-- <property name="defaultAutoCommit" value="false" /> -->
</bean>
<bean id="Second_dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="url" value="${Second_jdbc.url}" />
<property name="driverClassName" value="${Second_jdbc.driverClassName}" />
<property name="username" value="${Second_jdbc.username}" />
<property name="password" value="${Second_jdbc.password}" />
<property name="removeAbandoned" value="true" />
<property name="initialSize" value="20" />
<property name="maxActive" value="30" />
<!-- <property name="defaultAutoCommit" value="false" /> -->
</bean>
<bean id="First_TransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
scope="singleton">
<property name="dataSource" ref="First_dataSource" />
<qualifier value="SC_TM"></qualifier>
</bean>
<bean id="Second_TransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
scope="singleton">
<property name="dataSource" ref="Second_dataSource" />
<qualifier value="Second_TM"></qualifier>
</bean>
In code how do choose #Transactional("????") at run time.
If it is not possible with org.springframework.jdbc.datasource.DataSourceTransactionManager is there any other way of doing it?
Using #Transactional, you can specify the transaction manager like this:
#Transactional("First_TransactionManager")
or
#Transactional("Second_TransactionManager")
depending on which one you want to use. Make sure to use inside the transactional method the correct Entity Manager / session factory. Those you also have to specify which one you want to inject with #PersistenceContext("nameOfPersistenceUnit").
I do not know why you want to change between the 2 transaction manager may be you need to check Transaction manager chain solution, but in case you need this you can add your #transactional on Repo methods and do 2 Repos and manage it from the service layer as switch, otherwise I'm believing that there is solution could be done using AOP but it will need more time to think about it.
Problem is solved through AOP.
Define multiple data sources and corresponding Transacation Manager (as I have shown in my
base question)
First_dataSource mapped with First_TransactionManager and Second_dataSource mapped with Second_TransactionManager
Select which data source to use programatically depending on your business rules. In my case it was orgId
public class DataSourceProvider {
#Autowired
DataSource First_dataSource;
#Autowired
DataSource Second_dataSource;
public DataSource getDataSource(int orgId) {
if (orgId == Constants.BUSINESS_PARTY_1)
return Second_dataSource;
else
return First_dataSource;
}
public DataSource getFirst_dataSource() {
return First_dataSource;
}
public void setFirst_dataSource(DataSource First_dataSource) {
First_dataSource = First_dataSource;
}
public DataSource getSecond_dataSource() {
return Second_dataSource;
}
public void setSecond_dataSource(DataSource Second_dataSource) {
Second_dataSource = Second_dataSource;
}
}
AOP Configuration:
<tx:advice id="First_txAdvice" transaction-manager="First_TransactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="First_daoimplOperation"
expression="execution(* in.company.common.service.CommonServiceImpl.*(..))" />
<aop:advisor advice-ref="First_txAdvice" pointcut-ref="First_daoimplOperation" />
</aop:config>
<tx:advice id="Second_txAdvice" transaction-manager="Second_TransactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="Second_daoimplOperation"
expression="execution(* in.company.common.service.CommonServiceImpl.*(..))" />
<aop:advisor advice-ref="Second_txAdvice" pointcut-ref="Second_daoimplOperation" />
</aop:config>
all database related services should be in matching pointcut like in this case it is: in.company.common.service.CommonServiceImpl.*(..))
Consider using the Spring provided AbstractRoutingDataSource instead of going down the path of choosing between multiple transaction managers. It will be a much cleaner solution.
See my answer to a similar question here :
https://stackoverflow.com/a/44167079/2200690

Why does AOP managed transactions not work in my unit tests?

I've configured Spring solely based on XML. Transactions are managed by Hibernate, and I'm using AOP to manage transaction boundaries.
However, when running unit tests, why is it that my AOP configuration not kicks in? I need to add annotations such as #Transactional to the test method to make sure that database operations gets wrapped in transactions, even though I've configured AOP to wrap calls to service methods in transactions.
Why doesn't my AOP configuration apply to tests also?
applicationcontext.xml
<aop:aspectj-autoproxy/>
<!-- Data Source -->
<bean id="companyDomainDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.master.url}" />
<property name="user" value="${jdbc.master.username}" />
<property name="password" value="${jdbc.master.password}" />
<property name="acquireIncrement" value="1" />
<property name="minPoolSize" value="2" />
<property name="maxPoolSize" value="20" />
<property name="maxIdleTime" value="4" />
</bean>
<!-- Session Factory -->
<bean id="companyDomainSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="companyDomainDataSource"/>
<property name="mappingResources">
<list>
<value>/com/company/pas/entity/mapping/partner.hbm.xml</value>
</list>
</property>
</bean>
<!-- Transaction Manager -->
<bean id="companyDomainTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="companyDomainSessionFactory"/>
</bean>
<!-- Transaction Advice -->
<tx:advice id="companyDomainTransactionAdvise" transaction-manager="companyDomainTransactionManager">
<tx:attributes>
<!--<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>-->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="serviceMethods" expression="within(com.company.pas.dao.*)"/>
<aop:advisor advice-ref="companyDomainTransactionAdvise" pointcut-ref="serviceMethods"/>
</aop:config>
unit test
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"/applicationContext.xml"})
#TransactionConfiguration(transactionManager="companyDomainTransactionManager", defaultRollback=true)
public class PartnerCreateTest extends AbstractActionTest {
#Autowired #Qualifier("createPartnerAction") AbstractAction action;
#Test
#Transactional
public void testExecute() throws Exception {
// Create partner.
Representation rep = mock(Representation.class);
Request req = mock(Request.class);
Response resp = mock(Response.class);
when(rep.getText()).thenReturn(getContentsOf("com/company/pas/entity/xml/partner-create.xml"));
when(req.getEntity()).thenReturn(rep);
AbstractRequestModel crm = action.getRequestModelParser().parse(req, resp);
action.execute(crm);
}
}
When you add #Transactional to a test method you get a rollback by default. When you don't you should expect transactions to commit (they don't know they are in a test).

entitymanager is null on DAO class

I am trying to implement Spring MVC 3 +EclipseLink JPA 2
When I call saveUser for example it returns that
NullPointerException, EntityManager is
null
:
public class UserDAO {
#PersistenceContext
private EntityManager em;
public void setEntityManager(EntityManager em) {
this.em = em;
}
#Transactional
public User saveUser(User user){
return em.merge(user);
}
My config is:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="application" />
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.eclipse.persistence.platform.database.MySQLPlatform" />
<property name="generateDdl" value="false" />
</bean>
</property>
<property name="loadTimeWeaver">
<bean
class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver" />
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="username" value=".." />
<property name="password" value=".." />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://..." />
</bean>
Also have
<context:component-scan base-package="com.elasticbeanstalk.mypackage" />
<context:annotation-config />
It does initialize JPA during Tomcat startup. Why am I see NPE? Could I miss something?
If you instantiate the UserDAO manually, nothing will be injected by Spring. If the DAO is in a package which is under your base-package of <context:component-scan ../> then you can simply autowire it into your Controller. If not, either modify the base-package or also you can define the DAO in the appcontext manually, then you can autowire as well.

Resources