Sending mail with the user entered username and password in Spring - java

My application requires sending a mail from the user entered user name and password using Spring API. Here's how my Application Context file look.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:task="http://www.springframework.org/schema/task"
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/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<context:component-scan base-package="net.mail" />
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com"/>
<property name="port" value="25"/>
<property name="username" value="xyz#xyz.com" />
<property name="password" value="xyz" />
<property name="javaMailProperties">
<props>
<prop key="mail.transport.protocol">smtp</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.debug">true</prop>
</props>
</property>
</bean>
</beans>
And my Controller looks like following
package net.mail;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
public class MailController
{
#Autowired
MailSender sender;
#ResponseBody
#RequestMapping("/send")
public String sendMailToIt(HttpServletRequest request)
{
try
{
String from=request.getParameter("from");
String to=request.getParameter("to");
String sub=request.getParameter("subject");
String username=request.getParameter("username");
String password=request.getParameter("password");
//username and password should be used for authentication
SimpleMailMessage mail=new SimpleMailMessage();
mail.setFrom(from);
mail.setTo(to);
mail.setSubject(sub);
mail.setText("hello");
sender.send(mail);
}
catch(Exception e)
{
e.printStackTrace();
return "Exception Occured";
}
return new String("mail sent");
}
}
Now my requirements are
I don't want to use the properties file.
I want to username and password to be the ones entered by user.
I only found solutions using the properties file. but in my case i do not want to use that file.
Is there any way of doing so?

You can set in your MailController by getting data from the user ( set or override based on your requirement)
public String sendMailToIt(HttpServletRequest request)
{
.....
JavaMailSenderImpl jMailSender = (JavaMailSenderImpl)sender;
jMailSender.setUsername(userName);
jMailSender.setPassword(password);
....
jMailSender.send(mail);
....
}

Related

why EntityManager is null in spring transaction?

I wrote this code in the Service part of my java webapp project:
#Service
#Transactional
public class PersonService extends BaseService {
#PersistenceContext
private EntityManager entityManager;
public void insert(Person person) {
entityManager.persist(person);
}
public boolean checkUserName(String userName) {
try {
System.out.println("Entity null ni");
Person person = (Person) entityManager.createQuery("select entity from person entity where entity.USER_NAME=:userName")
.setParameter("userName", userName)
.getSingleResult();
if (person == null)
return true;
else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
When I tried to insert a new record without using the checkUserName method, the record would be inserted correctly and entityManager was not null in this condition but when I wanted to check repetitive userName I got NullPointerException.I checked every Object in my code that could be null finally I understand entityManager is null.why entityManager is null in Spring Transaction.this is spring.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<!--SpringMVC-->
<context:component-scan base-package="Laitec.Doctor"/>
<mvc:annotation-driven/>
<mvc:resources mapping="/resources/**" location="/resources/"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
</bean>
<!-- SpringTransaction-->
<bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="Laitec.Doctor.model.entity"/><!--ToPackageAddress-->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<!--<prop key="hibernate.hbm2ddl.auto">create-drop</prop>-->
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#localhost:1521:XE"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryBean"/>
</bean>
<tx:annotation-driven/>
</beans>
Maybe are you instantiating PersonService calling new PersonService() ? In this case Spring is not performing any operation and thus field 'entityManager' is null. You must get a bean from your Application Context
applicationContext.getBean(PersonService.class);
Or invoking it from a test or a controller
#RestController
#GetMapping("people")
public class PersonController() {
#Autowired
private PersonService personService;
#PostMapping
public void home(#RequestBody Person person) {
personService.insert(person);
}
}

#Transactional annotation in Spring

I have written the below code to implment the transaction management of spring using #transactional annotation. I still feel some changes are required
in my DAO layer. May I know what changes are required . Thanks in advance
#Controller
public class RestController {
#Autowired
DataServices dataServices;
#RequestMapping(value = "/v1/dist_list/{emailId}/members", method = RequestMethod.GET)
public #ResponseBody String getDistributionListMember(#PathVariable String emailId) throws Exception, SpringException {
String retStatus = null;
retStatus = dataServices.getDistributionListMember(emailId, callerId);
]
}
}
DataServices.java
package com.uniteid.services;
import com.uniteid.model.AIWSuser;
public interface DataServices {
public String getDistributionListMember(final String emailId, final String callerID) throws Exception;
}
Below is my service layer where I added the trasactional attribute
package com.uniteid.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.uniteid.dao.DataDao;
import com.uniteid.model.AIWSuser;
#Service("dataService")
public class DataServicesImpl implements DataServices {
#Autowired
DataDao dataDao;
#Transactional
public String getDistributionListMember(String emailId, String callerID)
throws Exception {
return dataDao.getDistributionListMember(emailId, callerID);
}
}
Below is my spring-config file
<?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:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
xmlns:tx="http://www.springframework.org/schema/tx">
<context:component-scan base-package="com.uniteid.controller" />
<mvc:annotation-driven
content-negotiation-manager="contentNegociationManager" />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:uniteidrest.properties" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url">
<value>${eidms.url}</value>
</property>
<property name="username">
<value>${eidms.username}</value>
</property>
<property name="password">
<value>${eidms.password}</value>
</property>
</bean>
<!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"
/> <property name="url" value="jdbc:oracle:thin:#nyvm0467.ptc.un.org:1521:EIDMSUAT"
/> <property name="username" value="DBO_EIDMSUAT" /> <property name="password"
value="NewPassDBO_EIDMSUAT" /> </bean> -->
<bean id="contentNegociationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="defaultContentType" value="application/json" />
<property name="ignoreAcceptHeader" value="true" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.uniteid.model.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.connection.pool_size">10</prop>
</props>
</property>
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean id="dataDao" class="com.uniteid.dao.DataDaoImpl"></bean>
<bean id="dataServices" class="com.uniteid.services.DataServicesImpl"></bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
It still feel I have not implemented the Transactional management properly in the below code. May I know what part of the code can be removed for me to implement it
package com.uniteid.dao;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.jdbc.Work;
import org.springframework.beans.factory.annotation.Autowired;
import com.uniteid.controller.RestController;
import com.uniteid.model.AIWSuser;
import com.uniteid.model.User;
public class DataDaoImpl implements DataDao
{
#Autowired
\
SessionFactory sessionFactory;
Session session = null;
Transaction tx = null;
static final Logger logger = Logger.getLogger(DataDaoImpl.class);
public String getDistributionListMember(final String emailId, final String callerID) throws Exception {
session = sessionFactory.openSession();
tx = session.beginTransaction();
final String[] returnVal2 = { "" };
session.doWork(new Work() {
public void execute(Connection connection) throws SQLException {
CallableStatement stmt = null;
String returnVal = "";
stmt = connection.prepareCall("{?=call WS_Distributionlistmember(?,?)}");
stmt.registerOutParameter(1, Types.VARCHAR);
stmt.setString(2, emailId);
stmt.setString(3, callerID);
stmt.execute();
returnVal = stmt.getString(1);
logger.info("RETURN VALUE in getDistributionListMember method :::::: " + returnVal);
returnVal2[0] = returnVal;
logger.info("Return Value " + returnVal);
stmt.close();
}
});
tx.commit();
session.close();
return returnVal2[0];
}
}
Your code:
public String getDistributionListMember(final String emailId, final String callerID) throws Exception {
session = sessionFactory.openSession();//This is bad
tx = session.beginTransaction();//This is bad
tx.commit();//This is bad
session.close();//This is bad
Correct should be:
public String getDistributionListMember(final String emailId, final String callerID) throws Exception {
session = sessionFactory.getCurrentSession();//good way
It is because you told spring to autowired sessionFactory and from now on spring is managing your hibernate session not you. So getCurrentSession() is correct way.
#M. Deinum Thanks to point it out.
Remove bean declaration for bean id transactionManager and set txManager instead of transactionManager in transaction-manager value. As you are using hibernate with spring so HibernateTransactionManager should be used instead of DatabaseTransactionManager to define transaction boundary. DatabaseTransactionManager is used when you directly interact with data source without using any ORM or JPA framework.
In your service class define transaction boundary for method as below annotation
#Transactional(readOnly = true, propagation = Propagation.SUPPORTS)

Spring Bean wrong path

I am getting this error and I can't figure out why. I believe its the path. Tried to change it several times but no success.
***************************
APPLICATION FAILED TO START
***************************
Description:
Field loginDelegate in com.codeEvaluator.controller.LoginController required a bean of type 'com.codeEvaluator.delegate.LoginDelegate' that could not be found.
Action:
Consider defining a bean of type 'com.codeEvaluator.delegate.LoginDelegate' in your configuration.
Process finished with exit code 1
This is my sprinBeanConfiguration.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="loginDelegate" class="com.codeEvaluator.delegate.LoginDelegate">
<property name="userService" ref="userService"></property>
</bean>
<bean id="userService" class="com.codeEvaluator.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<bean name="userDao" class="com.codeEvaluator.dao.impl.UserDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/codeevaluator" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
My springWeb.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.jcg" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/jsp/" />
<property name="suffix" value=".jsp" />
<import resource="springBeanConfiguration.xml"/>
Controller class
package com.codeEvaluator.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.codeEvaluator.delegate.LoginDelegate;
import com.codeEvaluator.viewBean.LoginBean;
#Controller
public class LoginController
{
#Autowired
private LoginDelegate loginDelegate;
#RequestMapping(value="/login",method=RequestMethod.GET)
public ModelAndView displayLogin(HttpServletRequest request, HttpServletResponse response, LoginBean loginBean)
{
ModelAndView model = new ModelAndView("login");
//LoginBean loginBean = new LoginBean();
model.addObject("loginBean", loginBean);
return model;
}
#RequestMapping(value="/login",method=RequestMethod.POST)
public ModelAndView executeLogin(HttpServletRequest request, HttpServletResponse response, #ModelAttribute("loginBean")LoginBean loginBean)
{
ModelAndView model= null;
try
{
boolean isValidUser = loginDelegate.isValidUser(loginBean.getUsername(), loginBean.getPassword());
if(isValidUser)
{
System.out.println("User Login Successful");
request.setAttribute("loggedInUser", loginBean.getUsername());
model = new ModelAndView("welcome");
}
else
{
model = new ModelAndView("login");
request.setAttribute("message", "Invalid credentials!!");
}
}
catch(Exception e)
{
e.printStackTrace();
}
return model;
}
}
This is a project view.
The login.jsp is inside de jsp package.
change to
<context:component-scan base-package="com.jcg, com.codeEvaluator" />
and your import should be something like this
<import resource="classpath:springBeanConfiguration.xml"/>
or
<import resource="classpath*:springBeanConfiguration.xml"/>
In your "sprinBeanConfiguration.xml" file add those annotations <context:component-scan base-package="com.codeEvaluator" /> and<context:annotation-config> to enable annotation "#Autowired"

Data doesn't add to database in test

I have this test:
#ContextConfiguration(locations = {"classpath:/test/BeanConfig.xml"})
public class CandidateServiceTest extends AbstractTransactionalJUnit4SpringContextTests{
#Autowired
CandidateService candidateService;
#BeforeClass
public static void initialize() throws Exception{
UtilMethods.createTestDb();
}
#Before
public void setup() {
TestingAuthenticationToken testToken = new TestingAuthenticationToken("testUser", "");
SecurityContextHolder.getContext().setAuthentication(testToken);
}
#After
public void cleanUp() {
SecurityContextHolder.clearContext();
}
#Test
public void add(){
Candidate candidate = new Candidate();
candidate.setName("testUser");
candidate.setPhone("88888");
candidateService.add(candidate);//here I should add data to database
List<Candidate> candidates = candidateService.findByName(candidate.getName());
Assert.assertNotNull(candidates);
Assert.assertEquals("88888", candidates.get(0).getPhone());
}
}
add function:
#Transactional
#Service("candidateService")
public class CandidateService {
public void add(Candidate candidate) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String login = auth.getName();
User user = utilService.getOrSaveUser(login);
candidate.setAuthor(user);
candidateDao.add(candidate);
}
...
}
add function in dao:
public Integer add(Candidate candidate) throws HibernateException{
Session session = sessionFactory.getCurrentSession();
if (candidate == null) {
return null;
}
Integer id = (Integer) session.save(candidate);
return id;
}
Usually candidateService.add(candidate) adds to the database normally, but in test it doesn't add to database. I checked the database after test to see it.
What could be the problem?
UPDATE
configuration:
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
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.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- Настраивает управление транзакциями с помощью аннотации #Transactional -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Менеджер транзакций -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- Непосредственно бин dataSource -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
p:url="jdbc:sqlserver://10.16.9.52:1433;databaseName=hhsystemTest;"
p:username="userNew"
p:password="Pass12345" />
<!-- Настройки фабрики сессий Хибернейта -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:test/hibernate.cfg.xml</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="hibernate.connection.charSet">UTF-8</prop>
<!-- <prop key="hibernate.hbm2ddl.auto">create-drop</prop> -->
</props>
</property>
</bean>
</beans>
Try adding the #Transactional annotation around the method in your test class.
This annotation creates a session that can interact with the database.
Issue a flush after the candidateService.add. There is a transaction around the test method, a commit (and flush) is only happening after the method execution. You have to 'fake' the commit by flushing the session. Simply inject the SessionFactory in your test class and call flush on the current session.
#ContextConfiguration(locations = {"classpath:/test/BeanConfig.xml"})
public class CandidateServiceTest extends AbstractTransactionalJUnit4SpringContextTests{
#Autowired
private SessionFactory sessionFactory;
#Test
public void add(){
Candidate candidate = new Candidate();
candidate.setName("testUser");
candidate.setPhone("88888");
candidateService.add(candidate);//here I should add data to database
sessionFactory.getCurrentSession().flush(); //execute queries to database
List<Candidate> candidates = candidateService.findByName(candidate.getName());
Assert.assertNotNull(candidates);
Assert.assertEquals("88888", candidates.get(0).getPhone());
}
}
And ofcourse make sure that your findByName method is also implemented correctly and using the same hibernate session!
You must auto wire your sessionDactory instance in the DAO using #Autowired And I would place the #Transactional annotation within each method of the DAO, rather than before he class definition of a service class. This is normally the way that it is done in annotation-driven Spring application.

How to Get Spring Quartz Trigger to Fire Using Scheduler

I have never used a quartz scheduler before and I am having trouble creating a Quartz Job. The trigger I have configured via a cronExpression does not fire and I do not see what I am missing.
Thanks in advance for any help or advice!
I am using:
quartz version 1.6.3
spring version 3.1.1
Scheduler:
<beans default-autowire="byName"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- Quartz Scheduler -->
<bean id="scheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource" ref="itc5DataSource" />
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
<property name="quartzProperties">
<props>
<prop key="org.quartz.scheduler.instanceName">${cepis.portal.scheduler.name}</prop>
<prop key="org.quartz.scheduler.instanceId">${cepis.portal.scheduler.instanceId}</prop>
<prop key="org.quartz.threadPool.class">${cepis.portal.scheduler.threadPool.class}</prop>
<prop key="org.quartz.threadPool.threadCount">${cepis.portal.scheduler.threadPool.threadCount}
</prop>
<prop key="org.quartz.jobStore.class">${cepis.portal.scheduler.jobStore.class}</prop>
<prop key="org.quartz.jobStore.isClustered">${cepis.portal.scheduler.jobStore.isClustered}</prop>
<prop key="org.quartz.jobStore.useProperties">${cepis.portal.scheduler.jobStore.useProperties}
</prop>
<prop key="org.quartz.jobStore.tablePrefix">${cepis.portal.scheduler.jobStore.tablePrefix}</prop>
<prop key="org.quartz.jobStore.driverDelegateClass">${cepis.portal.scheduler.jobStore.driverDelegateClass}
</prop>
<prop key="org.quartz.jobStore.selectWithLockSQL">${cepis.portal.scheduler.jobStore.selectWithLockSQL}
</prop>
</props>
</property>
<property name="jobDetails">
<list>
<ref bean="updateNoShowAppointmentJob" />
</list>
</property>
<property name="triggers">
<list>
<ref bean="updateNoShowTrigger" />
</list>
</property>
</bean>
<!-- ************************************************************************************************* -->
<bean id="updateNoShowAppointmentJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="name" value="CEPIS-UpdateNoShows" />
<property name="group" value="Appointments" />
<property name="jobClass" value="edu.uky.cepis.util.cron.job.UpdateNoShowAppointmentJob" />
</bean>
<!-- ************************************************************************************************* -->
<bean id="updateNoShowTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="name" value="UpdateNoShow" />
<property name="group" value="Appointments" />
<property name="jobDetail" ref="updateNoShowAppointmentJob" />
<!-- Do this every 60 seconds.-->
<property name="cronExpression" value="0 * * * * ?" />
</bean>
</beans>
Job:
/**
*
*/
package edu.uky.cepis.util.cron.job;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerException;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
import edu.uky.cepis.service.AdvisingSessionService;
import edu.uky.cepis.domain.AdvisingSession;
/**
* #author cawalk4
*
* Purpose: Update all appointments with a date before the current date time
* Setting the appointmentStatus to "No Show"
*
*/
public class UpdateNoShowAppointmentJob extends QuartzJobBean {
private static Logger log = Logger.getLogger(
UpdateNoShowAppointmentJob.class);
private AdvisingSessionService advisingSessionService;
private static String NO_SHOW = "No Show";
#Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
log.debug("Running UpdateNoShowAppointmentJob at " + new Date());
ApplicationContext appContext = null;
try {
appContext = (ApplicationContext) context.getScheduler()
.getContext().get("applicationContext");
} catch (SchedulerException se) {
System.err.println(se);
}
try {
advisingSessionService = (AdvisingSessionService) appContext
.getBean("advisingSessionService", AdvisingSessionService.class);
} catch (Exception e) {
System.err.println(e);
}
if (advisingSessionService != null) {
List<AdvisingSession> advisingSessionList =
new ArrayList<AdvisingSession>(0);
advisingSessionList = advisingSessionService.getNewNoShowAdvisingSessions();
if (advisingSessionList == null) {
log.debug("advisingSessionSlotlist is null.");
return;
} else if (advisingSessionList.isEmpty()) {
log.debug("There are no new No Show advising appointments.");
return;
}
log.debug("Total no show e-mails are: " + advisingSessionList.size());
// Update the appointments
for(AdvisingSession advisingSession : advisingSessionList){
advisingSessionService.updateAdvisingSession(
advisingSession,
advisingSession.getSessionType(),
NO_SHOW,
advisingSession.getPreSessionText(),
advisingSession.getSessionText(),
advisingSession.getStudentNotes(),
advisingSession.getAdvisorNotes(),
advisingSession.getAdvisingSessionSlot(),
advisingSession.getNoShowEmailSentBoolean());
}
} else {
log.debug("advisingSessionService is null.");
}
}
public void setadvisingSessionService(AdvisingSessionService advisingSessionService) {
this.advisingSessionService = advisingSessionService;
}
public AdvisingSessionService getadvisingSessionService() {
return advisingSessionService;
}
}
If you remove the portion of the XML that sets the jobDetails property of your scheduler bean, it should work as expected.
If you look at the javadoc for setTriggers on Spring's SchedulerAccessor class (that's the superclass of SchedulerFactoryBean), you can see that:
If the Trigger determines the corresponding JobDetail itself, the job
will be automatically registered with the Scheduler. Else, the
respective JobDetail needs to be registered via the "jobDetails"
property of this FactoryBean.
What they don't mention is that if you have already registered the JobDetail, it will prevent the Trigger from scheduling its referenced job. The source code for the addTriggerToScheduler method in SchedulerAccessor has this chunk of code:
JobDetail jobDetail = findJobDetail(trigger);
if (jobDetail != null) {
// Automatically register the JobDetail too.
if (!this.jobDetails.contains(jobDetail) && addJobToScheduler(jobDetail)) {
this.jobDetails.add(jobDetail);
}
}
You can see, then, that if the jobDetails already contains your job, the if condition will fail fast and the addJobToScheduler method will never be invoked.

Categories