Here is my #Service class whose remind() method is called from the front-end.
#Service
public class EmailManagerImpl implements EmailManager {
private MailSender mailSender;
private SimpleMailMessage templateMessage;
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
public void setTemplateMessage(SimpleMailMessage templateMessage) {
this.templateMessage = templateMessage;
}
#Override
public void remind(Appointment appointment) {
Person patient = appointment.getPatient();
SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage);
msg.setTo(patient.getMail());
msg.setText("Szanowny pacjencie " + patient.getFirstName() + " "
+ patient.getSurname() + " "
+ appointment.toString());
try {
mailSender.send(msg);
} catch (MailException ex) {
// log it and go on
System.err.println(ex.getMessage());
}
}
I am sure that templeMessage and mailSender are injected correctly. After whole process is executed i dont get any error, no exception no debugging info from true. When i try to run one of many demos, it works just fine. The only diffrence is that my application is on Tomcat + i invoke method from bean. Any ideas?
I can follow debug up to the following method from SimpleMailMessage line, later i get message that source is not found:
//---------------------------------------------------------------------
// Implementation of MailSender
//---------------------------------------------------------------------
public void send(SimpleMailMessage simpleMessage) throws MailException {
send(new SimpleMailMessage[] { simpleMessage });
}
My applicationConfig:
<!-- Wysylanie maili -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${mail.host}" />
<property name="port" value="${mail.port}" />
<property name="username" value="${mail.username}" />
<property name="password" value="${mail.password}" />
<property name="protocol" value="smtp" />
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.ssl.trust">smtp.gmail.com</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.smtps.debug">true</prop>
</props>
</property>
</bean>
<!-- this is a template message that we can pre-load with default state -->
<bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from" value="${mail.username}" />
<property name="subject" value="${mail.subject}" />
</bean>
<bean id="emailManagerImpl" class="com.przychodnia.rejestracja.integration.EmailManagerImpl">
<property name="mailSender"><ref bean="mailSender"/></property>
<property name="templateMessage"><ref bean="templateMessage"/></property>
</bean>
Related
I have the below configuration in application context xml file
<bean id="methodMapWithDefaultTxAttributeSource" class="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource">
<property name="transactionAttribute" value="PROPAGATION_REQUIRES_NEW,timeout_60"/>
</bean>
<bean id="methodMapTxInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="txManager"/>
<property name="transactionAttributeSource" ref="methodMapWithDefaultTxAttributeSource"/>
</bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<idref bean="retryAdvice"/>
<idref bean="methodMapTxInterceptor"/>
</list>
</property>
<property name="beanNames">
<value>service</value>
</property>
</bean>
<bean id="txProxyTemplate"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true">
<property name="transactionManager" ref="txManager" />
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRES_NEW,timeout_60</prop>
</props>
</property>
</bean>
<bean id="manager1" class="package2.Manager1">
<constructor-arg ref="dataSource"/>
</bean>
<bean id="manager2" class="package2.Manager2">
<constructor-arg ref="dataSource"/>
</bean>
<bean id="manager1TxProxy" parent="txProxyTemplate">
<property name="proxyTargetClass" value="true" />
<property name="target" ref="manager1" />
</bean>
<bean id="manager2TxProxy" parent="txProxyTemplate">
<property name="proxyTargetClass" value="true" />
<property name="target" ref="manager2"/>
</bean>
<bean id="retryPolicy" class="org.springframework.retry.policy.SimpleRetryPolicy">
<constructor-arg name="maxAttempts" value="3"/>
</bean>
<bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
<property name="retryPolicy" ref="retryPolicy"/>
</bean>
<bean id="rollbackClassifier" class="org.springframework.classify.BinaryExceptionClassifier">
<constructor-arg name="typeMap">
<util:map map-class="java.util.HashMap" key-type="java.lang.Class" value-type="java.lang.Boolean">
<entry key="java.lang.NullPointerException" value="false"/>
</util:map>
</constructor-arg>
<constructor-arg name="defaultValue" value="true"/>
<constructor-arg name="traverseCauses" value="true"/>
</bean>
<bean id="retryAdvice" class="org.springframework.retry.interceptor.StatefulRetryOperationsInterceptor">
<property name="retryOperations" ref="retryTemplate"/>
<property name="rollbackClassifier" ref="rollbackClassifier"/>
<property name="label" value="label"/>
</bean>
<bean id="service" class="package2.Service">
<property name="manager1" ref="manager1"/>
<property name="manager2" ref="manager2TxProxy"/>
</bean>
As you can see i have wrapped a interceptor chain around Service class method. The goal is add retry and transaction facility to all Service class method. I have modified the Service class below method to throw exception whenever it is called
public void executeWithException() {
manager1.execute();
throw new NullPointerException();
//manager2.execute();
}
Now in the first try, the interceptor chain has StatefulRetryOperationsInterceptor and TransactionInterceptor and before calling the Service class method transaction is created. The Service class method throws exception and it will retry.
Now in the second retry, the interceptor chain will have only StatefulRetryOperationsInterceptor and not TransactionInterceptor. I feel this is wrong. Even for second retry a new transaction has to be created. The javadoc says that. But is not happening here. The TransactionInterceptor is skipped.
Am i missing some configuration here.
Please help me out.
Screenshot of call stacktrace on first retry
Screenshot of call stacktrace on second retry
Hi Gary, I tried your example. I created my own transaction manager as shown below
public class MyTransactionManager extends AbstractPlatformTransactionManager {
private int i = 0;
#Override
protected Object doGetTransaction() throws TransactionException {
return new Object();
}
#Override
protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException {
System.out.println("Transaction" + i);
i = i + 1;
}
#Override
protected void doCommit(DefaultTransactionStatus status) throws TransactionException {
}
#Override
protected void doRollback(DefaultTransactionStatus status) throws TransactionException {
}
}
Used it in the xml file
<bean id="txManager" class="package2.MyTransactionManager"/>
Below is the console output
Transaction0
Manager1 Execute
Manager1 Execute
Manager1 Execute
Exception in thread "main"
As you see transaction doBegin method is called once printing "Transaction0". This shows new transactions are not created for every retry.
Below is the main method
public class Example2 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("example2.xml");
Service service1 = (Service)context.getBean("service");
service1.executeWithException();
}
}
When I debugged the code, TransactionInterceptor is in the chain but it is skipped on subsequent retry.
It makes no sense that the interceptor would change between calls; you must be mistaken.
It works fine for me with similar configuration as yours:
#SpringBootApplication
#ImportResource("so70609332-context.xml")
public class So70609332Application {
public static void main(String[] args) {
SpringApplication.run(So70609332Application.class, args);
}
#Bean
TransactionInterceptor txInterceptor(TransactionManager tm) {
return new TransactionInterceptor(tm, new MatchAlwaysTransactionAttributeSource());
}
#Bean
ApplicationRunner runner(Service service, MyTransactionManager tm) {
return args -> {
while (true) {
try {
callIt(service);
}
catch (IllegalStateException e) {
}
catch (Exception e) {
System.out.println(tm.begins);
break;
}
}
};
}
private void callIt(Service nt) {
try {
nt.foo();
}
catch (IllegalStateException e) {
throw e;
}
}
}
class Service {
void foo() {
System.out.println("called: " + TransactionSynchronizationManager.isActualTransactionActive());
throw new IllegalStateException();
}
}
#Component
class MyTransactionManager extends AbstractPlatformTransactionManager {
int begins;
#Override
protected Object doGetTransaction() throws TransactionException {
return new Object();
}
#Override
protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException {
this.begins++;
}
#Override
protected void doCommit(DefaultTransactionStatus status) throws TransactionException {
}
#Override
protected void doRollback(DefaultTransactionStatus status) throws TransactionException {
}
}
<?xml version="1.0" encoding="UTF-8"?>
<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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<idref bean="retryAdvice" />
<idref bean="txInterceptor" />
</list>
</property>
<property name="beanNames">
<value>service</value>
</property>
</bean>
<bean id="retryTemplate"
class="org.springframework.retry.support.RetryTemplate">
</bean>
<bean id="retryAdvice"
class="org.springframework.retry.interceptor.StatefulRetryOperationsInterceptor">
<property name="retryOperations" ref="retryTemplate" />
<property name="label" value="label" />
</bean>
<bean id="service" class="com.example.demo.Service" />
</beans>
called: true
called: true
called: true
3
I'm trying to insert data into table using Spring MVC+Hibernate. Table is geting creating but code throwing exception at template.save() method calling in CompanyDao file. Please help to solve this.
I have tested if company object is null but company object having all data but template in null.
File: CompanyDao.java
import org.springframework.orm.hibernate5.HibernateTemplate;
public class CompanyDao {
HibernateTemplate template;
public void setTemplate(HibernateTemplate template) {
this.template = template;
}
//method to save Company
public void saveCompany(Company c){
if(c!=null) {
template.save(c);
}
else {
System.out.print("company object is null");
}
}
}
ApplicationContext.xml
<bean id="mysessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mappingResources">
<list>
<value>company.hbm.xml</value>
<!-- <value>address.hbm.xml</value> -->
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="mysessionFactory"></property>
</bean>
<bean id="template" class="dao.CompanyDao">
<property name="template" ref="hibernateTemplate"></property>
</bean>
File Controller:
#RequestMapping("/submitCompanyRegForm")
public ModelAndView submitCompanyRegForm(#ModelAttribute("companyMo") Company comp)
{
CompanyDao companydao = new CompanyDao();
companydao.saveCompany(comp);
ModelAndView model = new ModelAndView("submitcompanyreg");
return model;
}
I am developing a service in Spring and I can send email when I am running this same app from my development machine, but when I deploy it to a server it does not work.
I checked from the server with Swaks and it also works from command line but it's not working from Spring.
Here is the Spring configuration:
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="my-domain.tld"/>
<property name="port" value="587"/>
<property name="username" value="myemail#my-domain.tld"/>
<property name="password" value="mypassword"/>
<property name="defaultEncoding" value="UTF-8"/>
<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>
It stops after this line(from log file)
STARTTLS
220 2.0.0 Ready to start TLS
Here is the code to send email
#Component
public class EmailProvider {
#Autowired
private JavaMailSender mailSender;
#Async
public void sendEmail(final String to, final String subject, final String body, final String cc, final String bcc, final boolean html) {
if (StringUtils.isEmpty(to) || StringUtils.isEmpty(subject) || StringUtils.isEmpty(body)) {
return;
}
MimeMessagePreparator message = new MimeMessagePreparator() {
#Override
public void prepare(MimeMessage mmsg) throws Exception {
MimeMessageHelper mm = new MimeMessageHelper(mmsg);
mm.setTo(new InternetAddress(to));
mm.setSubject(subject);
mm.setFrom("from#my-domain.tld");
if (StringUtils.isNotEmpty(cc)) {
mm.setCc(cc);
}
if (StringUtils.isNotEmpty(bcc)) {
mm.setBcc(bcc);
}
mm.setText(body, html);
}
};
mailSender.send(message);
}
}
Thanks in advance.
I've read tens of topics and no result.
What the problem:
I can't get current hibernate session in #Transactional method.
EXCEPTION:
Exception in thread "main" org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:988)
at name.krestjaninoff.activiti.hello.core.Engine.getHibernateSession(Engine.java:27)
at name.krestjaninoff.activiti.hello.process.CreateClientService.execute(CreateClientService.java:42)
at org.activiti.engine.impl.bpmn.JavaDelegateDelegate.execute(JavaDelegateDelegate.java:48)
at org.activiti.engine.impl.bpmn.JavaDelegateDelegate.execute(JavaDelegateDelegate.java:39)
at org.activiti.engine.impl.bpmn.ClassDelegate.execute(ClassDelegate.java:96)
at org.activiti.engine.impl.pvm.runtime.AtomicOperationActivityExecute.execute(AtomicOperationActivityExecute.java:40)
....
My Code:
#Service
#EnableTransactionManagement(proxyTargetClass=true, mode= AdviceMode.PROXY)
public class CreateClientService {
#Transactional(value="transactionManager", propagation = Propagation.REQUIRED)
public void execute() {
((SessionFactory) applicationContext.getBean("sessionFactory")).getCurrentSession(); //EXCEPTOIN!!!
}
}
My configurations:
<tx:annotation-driven/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" scope="singleton">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan">
<list>
<value>name.krestjaninoff.activiti.hello.db</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL82Dialect</prop>
<!--<prop key="hibernate.hbm2ddl.auto">create</prop>-->
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager" scope="singleton">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
<property name="dataSource">
<ref local="dataSource" />
</property>
</bean>
ADDTION: NativeConstructorAccessorImpl class create CreateClientService instance:
#CallerSensitive
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers);
}
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
ca = acquireConstructorAccessor();
}
return (T) ca.newInstance(initargs);
}ected JavaDelegate javaDelegate;
protected JavaDelegateDelegate() {
}
public JavaDelegateDelegate(JavaDelegate javaDelegate) {
this.javaDelegate = javaDelegate;
}
public void execute(ActivityExecution execution) throws Exception {
execute((DelegateExecution) execution);
performDefaultOutgoingBehavior(execution);
}
public void notify(ExecutionListenerExecution execution) throws Exception {
execute((DelegateExecution) execution);
}
public void execute(DelegateExecution execution) throws Exception {
javaDelegate.execute(execution);
}
}
I'm using Spring 3.1.0.RELEASE with Hibernate 4.0.1.Final. I'm trying to use the Spring transaction manager but am having an issue where Spring is returning old data for a find method. In my Spring application, I call a save method, and then a find method. After I call save, I can see the changes in the database, but when I call the find, it is returning the old state of the object. Here is the controller methods ...
// method to save
#RequestMapping(method = RequestMethod.POST)
public String saveUserEventFeeds(final HttpServletRequest request,
#ModelAttribute("eventFeeds") final Set<EventFeed> eventFeeds) {
final String nextPage = "user/eventfeeds";
try {
final String[] eventFeedIds = request.getParameterValues("userEventFeeds");
final Set<EventFeed> userEventFeeds = new HashSet<EventFeed>();
if (eventFeedIds != null) {
for (final String eventFeedId : eventFeedIds) {
final EventFeed eventFeed = getEventFeed(eventFeeds, Integer.parseInt(eventFeedId));
userEventFeeds.add(eventFeed);
} // for
} // if
final Registration currentUser = (Registration) securityContextFacade.getContext().getAuthentication().getPrincipal();
userService.saveUserEventFeeds(currentUser.getId(), userEventFeeds);
} catch (Exception exc) {
LOG.error(exc.getMessage(), exc);
} // try
return nextPage;
} // saveUserEventFeeds
// method to retrieve user
#ModelAttribute("user")
public UserDetails getUser() {
final Registration reg = (Registration) securityContextFacade.getContext().getAuthentication().getPrincipal();
final int id = reg.getId();
final Registration foundUser = userService.findUserById(id);
return (UserDetails) foundUser;
} // getUser
and here is the service where i declare everything transactional ...
#Transactional(rollbackFor = Exception.class)
#Component("userService")
public class UserServiceImpl implements UserService {
...
#Override
public void saveUserEventFeeds(Integer userId, Set<EventFeed> eventFeeds) {
final Registration searchUser = new Registration();
searchUser.setId(userId);
final Registration user = usersDao.getUser(searchUser);
if (user != null) {
user.setUserEventFeeds(eventFeeds);
usersDao.saveUser(user);
} else {
throw new RuntimeException("User with id " + userId + " not found.");
} // if
}
#Override
public Registration findUserById(Integer id) {
final Registration searchUser = new Registration();
if (id != null) {
searchUser.setId(id);
} // if
return usersDao.getUser(searchUser);
}
Below is the transaction manager I've declared in my application context file. If you can see how I can configure things differently so that I can get the most current data on my finds, please let me know.
<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/myproj"/>
<property name="username" value="myproj"/>
<property name="password" value="password"/>
<property name="maxActive" value="10"/>
<property name="minIdle" value="5"/>
<!-- SELECT 1 is a simple query that returns 1 row in MySQL -->
<property name="validationQuery" value="SELECT 1"/>
</bean>
<bean class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" id="sessionFactory">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.myco.myproj.domain.Registration</value>
<value>com.myco.myproj.domain.Role</value>
<value>com.myco.myproj.domain.EventFeed</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="show_sql">true</prop>
<prop key="dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
<tx:annotation-driven />