java.lang.NullPointerException what I'm doing wrong? - spring-boot

I'm working on a project in which my intention is to run a Corn job and send mail to my friends to wishing them on their birthday, I was able to get email from MySQL DB and compared it to the current date but when it comes to sending an email I'm getting NullPointerException.
I'm sure there is no problem with application properties I used them with other projects as well and they are function properly
//Imports
package dev.teja.happybirthday;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.*;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.persistence.*;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.validation.constraints.Email;
import freemarker.template.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.bind.annotation.*;
//Main
#SpringBootApplication
public class HappybirthdayApplication {
public static void main(String[] args) {
SpringApplication.run(HappybirthdayApplication.class, args);
}
#Autowired
MyFriendsRepository myFriendsRepository ;
#Scheduled(cron = "*/30 * * * * *")
void WishMyFriends() {
List<MyFriends> myFriendsList = myFriendsRepository.findAll();
myFriendsList.forEach(friend -> {
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM");
String CurrentDate= formatter.format(date);
String GivenDate = formatter.format(friend.dob);
if (GivenDate.equals(CurrentDate)){
Job job = new Job();
Map<String, Object> model = new HashMap<>();
model.put("Name",friend.name);
job.sendWish(friend.email,model);
}
});
}
}
#Configuration
#ConditionalOnProperty(name = "scheduling.enabled", matchIfMissing = true)
#EnableScheduling
class Tasks {
}
//Model
#Data
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
class MyFriends {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
String name;
#Email
#Column(unique = true)
String email;
#JsonFormat(pattern = "dd/MM/yyyy", shape = JsonFormat.Shape.STRING)
Date dob;
Long phoneNumber;
}
//Repository
interface MyFriendsRepository extends JpaRepository<MyFriends, Long> {
}
#RestController
#RequestMapping("/")
class FriendsController {
#Autowired
MyFriendsRepository myFriendsRepository;
#PostMapping("/friends")
ResponseEntity<MyFriends> createFriend(#RequestBody MyFriends myFriend) {
myFriendsRepository.save(myFriend);
return new ResponseEntity<MyFriends>(myFriend, HttpStatus.CREATED);
}
#GetMapping("/friends")
List<MyFriends> getFriends() {
return myFriendsRepository.findAll();
}
}
//Interface
interface wisher{
void sendWish(String email, Map<String, Object> model);
}
//Implementation
#Service
class Job implements wisher{
#Autowired
private JavaMailSender sender;
#Autowired
private freemarker.template.Configuration config;
#Override
public void sendWish(String email,Map<String, Object> model) {
System.out.println("wishes sent to "+ email);
MimeMessage message = sender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
StandardCharsets.UTF_8.name());
Template template = config.getTemplate("new-template.ftl");
String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
helper.setTo(email);
helper.setFrom("kondasaitej#gmail.com");
helper.setSubject("Happy Birthday");
helper.setText(html,true);
sender.send(message);
} catch (MessagingException | IOException | TemplateException e) {
e.printStackTrace();
}
}
}
FreeMaker file in ./resources/Templates
/**
* FREEMAKER new-template.ftl
* <html xmlns="http://www.w3.org/1999/xhtml">
* <head>
* <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
* <title>Comment Alert Mail</title>
* </head>
* <body>
* <p>happy birthday ${Name}</p>
* </body>
*/
This is the error I'm getting this following
Hibernate: select myfriends0_.id as id1_0_, myfriends0_.dob as dob2_0_, myfriends0_.email as email3_0_, myfriends0_.name as name4_0_, myfriends0_.phone_number as phone_nu5_0_ from my_friends myfriends0_
wishes sent to kondasaitej#protonmail.com
2020-09-26 21:01:52.012 ERROR 84242 --- [ scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task
java.lang.NullPointerException: null
at dev.teja.happybirthday.Job.sendWish(HappybirthdayApplication.java:115) ~[classes/:na]
at dev.teja.happybirthday.HappybirthdayApplication.lambda$WishMyFriends$0(HappybirthdayApplication.java:53) ~[classes/:na]
at java.util.ArrayList.forEach(ArrayList.java:1257) ~[na:1.8.0_251]
at dev.teja.happybirthday.HappybirthdayApplication.WishMyFriends(HappybirthdayApplication.java:44) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_251]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_251]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_251]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_251]
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93) [spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_251]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_251]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_251]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_251]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_251]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_251]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_251]

Try add getting in the #Autowired private JavaMailSender sender;

I think you have not implemented your JavaMailSender bean. Define a bean like below. Then your #Autowire annotation will work.
#Bean
public JavaMailSender getJavaMailSender()
{
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("smtp.gmail.com");
mailSender.setPort(25);
mailSender.setUsername("admin#gmail.com");
mailSender.setPassword("password");
Properties props = mailSender.getJavaMailProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.debug", "true");
return mailSender;
}

Related

Issue in Kafka Spring boot test cases for AdminClient

I am writing unit test cases for below class . I'm trying to mock admin client , so that i can call the below method create topic. But getting null pointer exception.
#Service
public class TopicService {
private static final Logger LOG = LoggerFactory.getLogger(TopicService.class);
#Autowired
private AdminClient adminClient;
public void createTopic(Topic topic) throws ExecutionException, InterruptedException {
adminClient
.createTopics(Collections.singletonList(ServiceHelper.fromTopic(topic)))
.values()
.get(topic.getName())
.get();
}
}
The unit test case is as follows
package org.kafka.service;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.admin.AdminClient;
import org.apache.kafka.clients.admin.CreateTopicsResult;
import org.apache.kafka.clients.admin.ListTopicsResult;
import org.apache.kafka.clients.admin.NewTopic;
import org.apache.kafka.common.KafkaFuture;
import org.apache.kafka.common.internals.KafkaFutureImpl;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kafka.model.Topic;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.*;
import java.util.concurrent.ExecutionException;
import static org.apache.kafka.clients.admin.AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG;
import static org.apache.kafka.clients.admin.AdminClientConfig.REQUEST_TIMEOUT_MS_CONFIG;
import static org.apache.kafka.common.internals.Topic.GROUP_METADATA_TOPIC_NAME;
#Slf4j
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {TopicService.class})
public class TopicServiceTest {
#Autowired
TopicService topicService;
#MockBean
AdminClient adminClient;
ListTopicsResult listTopicsResult;
KafkaFuture<Set<String>> future;
NewTopic newTopic;
Topic topic;
Collection<NewTopic> topicList;
CreateTopicsResult createTopicsResult;
Void t;
Map<String,KafkaFuture<Void>> futureMap;
private static final String TARGET_CONSUMER_GROUP_ID = "target-group-id";
private static final Map<String, Object> CONF = new HashMap<>();
#BeforeClass
public static void createAdminClient() {
try {
CONF.put(BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
CONF.put(REQUEST_TIMEOUT_MS_CONFIG, 120000);
CONF.put("zookeeper.connect", "localhost:21891");
AdminClient adminClient = AdminClient.create(CONF);
} catch (Exception e) {
throw new RuntimeException("create kafka admin client error", e);
}
}
#Before
public void setUp(){
topicList = new ArrayList<>();
newTopic = new NewTopic("topic-7",1, (short) 1);
topicList.add(newTopic);
futureMap = new HashMap<>();
topic = new Topic();
topic.setName("topic-1");
}
#Test
public void createTopic() throws ExecutionException, InterruptedException {
Properties consumerProperties = new Properties();
Mockito.when(adminClient.createTopics(topicList))
.thenReturn(Mockito.mock(CreateTopicsResult.class));
Mockito.when(adminClient.createTopics(topicList).values())
.thenReturn(Mockito.mock(Map.class));
Mockito.when(adminClient.createTopics(topicList)
.values()
.get(GROUP_METADATA_TOPIC_NAME)).thenReturn(Mockito.mock(KafkaFutureImpl.class));
Mockito.when(adminClient.createTopics(topicList)
.values()
.get(GROUP_METADATA_TOPIC_NAME)
.get()).thenReturn(t);
topicService.createTopic(topic);
}
}
package org.kafka.config;
import org.apache.kafka.clients.admin.AdminClient;
import org.apache.kafka.clients.admin.AdminClientConfig;
import org.kafka.reader.Kafka;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.core.KafkaAdmin;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
#Component
public class AdminConfigurer {
#Autowired
private Kafka kafkaConfig;
#Bean
public Map<String, Object> kafkaAdminProperties() {
final Map<String, Object> configs = new HashMap<>();
configs.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaConfig.getBootstrapServers());
if(kafkaConfig.getProperties().getSasl().getEnabled() && kafkaConfig.getSsl().getEnabled()) {
configs.put("sasl.mechanism", kafkaConfig.getProperties().getSasl().getMechanism());
configs.put("security.protocol", kafkaConfig.getProperties().getSasl().getSecurity().getProtocol());
configs.put("ssl.keystore.location", kafkaConfig.getSsl().getKeystoreLocation());
configs.put("ssl.keystore.password", kafkaConfig.getSsl().getKeystorePassword());
configs.put("ssl.truststore.location", kafkaConfig.getSsl().getTruststoreLocation());
configs.put("ssl.truststore.password", kafkaConfig.getSsl().getTruststorePassword());
configs.put("sasl.jaas.config", String.format(kafkaConfig.getJaasTemplate(),
kafkaConfig.getProperties().getSasl().getJaas().getConfig().getUsername(),
kafkaConfig.getProperties().getSasl().getJaas().getConfig().getPassword()));
configs.put("ssl.endpoint.identification.algorithm", "");
}
return configs;
}
#Bean
public AdminClient getClient() {
return AdminClient.create(kafkaAdminProperties());
}
}
I expected the below test case run successfully. But i'm getting below error.
java.lang.NullPointerException
at org.kafka.service.TopicService.createTopic(TopicService.java:57)
at org.kafka.service.TopicServiceTest.createTopic(TopicServiceTest.java:100)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
I'm using 2.7.1 spring version with following client dependency.
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>3.1.1</version>
<scope>test</scope>
<classifier>test</classifier>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>

How to use two data source for same entity in spring boot application running on tomcat

I have one micro-service named order-service in spring boot.
:: Spring Boot :: (v2.0.5.RELEASE)
in that micro-service, in service layer I have 2 service class 1. OrderManagerService and OrderService. From OrderService I call Repository Interface IOrderRequestRepository which extends PagingAndSortingRepository interface. so The call is basically OrderManagerService -> OrderService -> IOrderRequestRepository.
Right now I am using one data source for the micro-service. Now my requirement is I have to use 2 data source because in OrderManagerService there is one method getCustomerVisitsForMonth(Long customerID) which frequently used and we don't want to give load on prod DB server. Instead we will use prod-replica server for this one particular method.
I have googled a lot of blogs and tried to implement but ending up getting different exception.
below are exceptions:
could not execute query; SQL [SELECT * FROM ....(this is the actual query)]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query",
Could not open JPA EntityManager for transaction; nested exception is org.hibernate.TransactionException: JDBC begin transaction failed:
Below are my sample code:
application-env.properties
spring.datasource.url=jdbc:mysql://someurl:3306/orders?zeroDateTimeBehavior=convertToNull&useSSL=false
spring.datasource.username=<username>
spring.datasource.password=<password>
spring.datasource.driverClassName=com.mysql.jdbc.Driver
#replica datasource details
spring.replica.datasource.url=jdbc:mysql://someurl:3306/order?zeroDateTimeBehavior=convertToNull&useSSL=false
spring.replica.datasource.username=<username>
spring.replica.datasource.password=<password>
spring.replica.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.tomcat.initial-size=15
spring.datasource.tomcat.max-wait=20000
spring.datasource.tomcat.max-active=5
spring.datasource.tomcat.max-idle=4
spring.datasource.tomcat.min-idle=2
spring.datasource.tomcat.default-auto-commit=true
#replica data source details
spring.replica.datasource.tomcat.initial-size=15
spring.replica.datasource.tomcat.max-wait=20000
spring.replica.datasource.tomcat.max-active=5
spring.replica.datasource.tomcat.max-idle=4
spring.replica.datasource.tomcat.min-idle=2
spring.replica.datasource.tomcat.default-auto-commit=true
Main class
package in.demo.order.web.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#SpringBootApplication(scanBasePackages = "in.demo.order",
exclude = { SecurityAutoConfiguration.class })
public class OrderServiceApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(OrderServiceApplication.class);
}
}
I have created 2 different packages for Repository classes and for Entity classes, however my Entity and Repository are same.
packages
in.demo.order.dao
in.demo.order.repodao
Configuration classes
MainDataSourceConfiguration
package in.demo.order.web.config;
import in.demo.order.replicadao.IOrderRequestRepositoryForReplica;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
basePackages = "in.demo.order.dao",
entityManagerFactoryRef = "mainEntityManagerFactory",
transactionManagerRef = "mainTransactionManager"
)
public class MainDataSourceConfiguration {
#Autowired
private Environment environment;
#Primary
#Bean(name = "mainDataSourceProperties")
#ConfigurationProperties("spring.datasource")
public DataSourceProperties mainDataSourceProperties() {
return new DataSourceProperties();
}
#Primary
#Bean(name = "mainDataSource")
#ConfigurationProperties("spring.datasource.configuration")
public DataSource mainDataSource(
#Qualifier("mainDataSourceProperties") DataSourceProperties mainDataSourceProperties) {
return mainDataSourceProperties
.initializeDataSourceBuilder()
.type(org.apache.tomcat.jdbc.pool.DataSource.class)
.build();
}
#Primary
#Bean(name = "mainEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean mainEntityManagerFactory(
EntityManagerFactoryBuilder mainEntityManagerFactoryBuilder,
#Qualifier("mainDataSource") DataSource mainDataSource) {
Map<String, String> mainJpaProperties = new HashMap<>();
mainJpaProperties.put("hibernate.dialect",
environment.getProperty("spring.jpa.properties.hibernate.dialect"));
mainJpaProperties.put("hibernate.hbm2ddl.auto",
environment.getProperty("spring.jpa.hibernate.ddl-auto"));
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = mainEntityManagerFactoryBuilder
.dataSource(mainDataSource)
.packages("in.demo.order.dao.model")
.persistenceUnit("mainDataSource")
.properties(mainJpaProperties)
.build();
localContainerEntityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
return localContainerEntityManagerFactoryBean;
}
#Primary
#Bean(name = "mainTransactionManager")
public PlatformTransactionManager mainTransactionManager(
#Qualifier("mainEntityManagerFactory") EntityManagerFactory mainEntityManagerFactory) {
return new JpaTransactionManager(mainEntityManagerFactory);
}
}
ReplicaDataSourceConfiguration
package in.demo.order.web.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
basePackages = "in.demo.order.replicadao",
entityManagerFactoryRef = "replicaEntityManagerFactory",
transactionManagerRef = "replicaTransactionManager"
)
public class ReplicaDataSourceConfiguration {
#Autowired
private Environment environment;
#Bean(name = "replicaDataSourceProperties")
#ConfigurationProperties("spring.replica.datasource")
public DataSourceProperties replicaDataSourceProperties() {
return new DataSourceProperties();
}
#Bean(name = "replicaDataSource")
#ConfigurationProperties("spring.replica.datasource.configuration")
public DataSource replicaDataSource(
#Qualifier("replicaDataSourceProperties") DataSourceProperties replicaDataSourceProperties) {
return replicaDataSourceProperties
.initializeDataSourceBuilder()
.type(org.apache.tomcat.jdbc.pool.DataSource.class)
.build();
}
#Bean(name = "replicaEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean replicaEntityManagerFactory(
EntityManagerFactoryBuilder replicaEntityManagerFactoryBuilder,
#Qualifier("replicaDataSource") DataSource replicaDataSource) {
Map<String, String> replicaJpaProperties = new HashMap<>();
replicaJpaProperties.put("hibernate.dialect",
environment.getProperty("spring.jpa.properties.hibernate.dialect"));
replicaJpaProperties.put("hibernate.hbm2ddl.auto",
environment.getProperty("spring.jpa.hibernate.ddl-auto"));
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = replicaEntityManagerFactoryBuilder
.dataSource(replicaDataSource)
.packages("in.demo.order.replicadao.model")
.persistenceUnit("replicaDataSource")
.properties(replicaJpaProperties)
.build();
localContainerEntityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
return localContainerEntityManagerFactoryBean;
}
#Bean(name = "replicaTransactionManager")
public PlatformTransactionManager replicaTransactionManager(
#Qualifier("replicaEntityManagerFactory") EntityManagerFactory replicaEntityManagerFactory) {
return new JpaTransactionManager(replicaEntityManagerFactory);
}
}
OrderManagerService
package in.demo.order.service;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
#Transactional
public class OrderManagerService{
#Autowired
private OrderService orderService;
public CustomerVisitsResponse getCustomerVisitsForMonthForReplicaDataSource(Long customerId) {
return orderService.getTotalCustomerVisitsForMonth(customerId);
}
public CustomerVisitsResponse getCustomerVisitsForMonthForMainDataSource(Long customerId) {
return orderService.getTotalCustomerVisitsForMonthForMainDataSource(customerId);
}
}
OrderService
package in.demo.order.service;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import in.demo.order.replicadao.IOrderRequestRepositoryForReplica;
import in.demo.order.dao.IOrderRequestRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service
#Transactional(rollbackFor = Exception.class)
public class OrderService {
#Autowired
private IOrderRequestRepositoryForMain orderRequestRepositoryForMain;
#Autowired
private IOrderRequestRepositoryForReplica orderRequestRepositoryForReplica;
public CustomerVisitsResponse getTotalCustomerVisitsForMonthForReplicaDataSource(Long customerId) {
List<Integer> statusIdList= new ArrayList<>();
CustomerVisitsResponse response= new CustomerVisitsResponse();
statusIdList.add(OrderServiceConstants.SOME_CONSTANT_VALUE);
List<Integer> sellerIdList= new ArrayList<>();
sellerIdList.add(OrderServiceConstants.SOME_CONSTANT_VALUE);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM");
Date date = new Date();
String month= dateFormat.format(date)+"%";
try {
List<in.demo.order.replicadao.model.OrderEntity> orders =
orderRequestRepositoryForReplica.getOrderBycustomerIdAndBdMonth(customerId,statusIdList,month,sellerIdList);
if(orders!=null && !orders.isEmpty())
{
double total=0d;
for(in.demo.order.replicadao.model.OrderEntity order:orders)
{
total+=order.getPayableAmount();
}
response.setTotalSpent(total);
response.setTotalVisits((long)(orders.size()));
}
else {
response.setTotalSpent(0d);
response.setTotalVisits(0l);
}
} catch (Exception e) {
logger.info("Error occured while fetching getTotalCustomerVisitsForMonth customerid: " + customerId);
response.setTotalSpent(0d);
response.setTotalVisits(0l);
return response;
}
return response;
}
public CustomerVisitsResponse getTotalCustomerVisitsForMonthForMainDataSource(Long customerId) {
List<Integer> statusIdList= new ArrayList<>();
CustomerVisitsResponse response= new CustomerVisitsResponse();
statusIdList.add(OrderServiceConstants.SOME_CONSTANT_VALUE);
List<Integer> sellerIdList= new ArrayList<>();
sellerIdList.add(OrderServiceConstants.SOME_CONSTANT_VALUE);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM");
Date date = new Date();
String month= dateFormat.format(date)+"%";
try {
List<in.demo.order.dao.model.OrderEntity> orders =
orderRequestRepositoryForMain.getOrderBycustomerIdAndBdMonth(customerId,statusIdList,month,sellerIdList);
if(orders!=null && !orders.isEmpty())
{
double total=0d;
for(in.demo.order.dao.model.OrderEntity order:orders)
{
total+=order.getPayableAmount();
}
response.setTotalSpent(total);
response.setTotalVisits((long)(orders.size()));
}
else {
response.setTotalSpent(0d);
response.setTotalVisits(0l);
}
} catch (Exception e) {
logger.info("Error occured while fetching getTotalCustomerVisitsForMonth customerid: " + customerId);
response.setTotalSpent(0d);
response.setTotalVisits(0l);
return response;
}
return response;
}
}
Repository classes
package in.demo.order.replicadao;
IOrderRequestRepositoryForReplica
package in.demo.order.replicadao;
import in.demo.order.replicadao.model.OrderEntity;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface IOrderRequestRepositoryForReplica extends PagingAndSortingRepository<OrderEntity, Long> {
#Query(nativeQuery = true,
value = "SELECT * FROM orders ...<some query>")
public List<OrderEntity> getOrderBycustomerIdAndBdMonth(
Long customerId, List<Integer> statusIdList, String month, List<Integer> sellerIdList);
}
package in.demo.order.dao;
IOrderRequestRepositoryForMain
package in.demo.order.dao;
import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import in.demo.order.dao.model.OrderEntity;
#Repository
public interface IOrderRequestRepositoryForMain extends PagingAndSortingRepository<OrderEntity, Long> {
#Query(nativeQuery = true,
value = "SELECT * FROM orders ...<some query>")
public List<OrderEntity> getOrderBycustomerIdAndBdMonth(Long customerId,
List<Integer> statusIdList, String month, List<Integer> sellerIdList);
}
Same Entity in different package with different serialVersionUID
packages are:
package in.demo.order.replicadao.model;
package in.demo.order.dao.model;
OrderEntity
package in.demo.order.replicadao.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "orders")
public class OrderEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 4667868888563693990L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique = true)
private String orderId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
}
Controller class
OrderController
package in.demo.order.controller;
import java.util.List;
import javax.sql.DataSource;
import in.demo.order.service.OrderManagerService;
#RestController
#RequestMapping("/api/order")
public class OrderController {
#Autowired
private OrderManagerService orderManagerService;
#Autowired
private DataSource mainDataSource;
#Autowired
#Qualifier("replicaDataSource")
private DataSource replicaDataSource;
#GetMapping("/replica")
public CustomerVisitsResponse getCustomerVisitResponseForReplica() {
Long customerId = 123L;
return orderManagerService.getCustomerVisitsForMonthForReplicaDataSource(customerId);
}
#GetMapping("/main")
public CustomerVisitsResponse getCustomerVisitResponseForMain() {
Long customerId = 123L;
return orderManagerService.getCustomerVisitsForMonthForMainDataSource(customerId);
}
#GetMapping("/maindatasource")
public String getMainDataSource() {
return mainDataSource.toString();
}
#GetMapping("/replicadatasource")
public String getReplicaDataSource() {
return replicaDataSource.toString();
}
}
I have checked manually in both Database for the query I am running. Data is present. But when I am running from postman to test
for replica, I am getting
Method threw 'org.springframework.dao.InvalidDataAccessResourceUsageException' exception. caused by org.hibernate.exception.SQLGrammarException: could not execute query
for main, I am getting
Transaction was marked for rollback only; cannot commit; nested exception is org.hibernate.TransactionException: Transaction was marked for rollback only; cannot commit
When I am using one datasource, the query is working fine.
The issue was with Entity class column name mapping issue, previously we were not mentioning #Column(name="column_name") , once I added the annotation, it started to work. But still I am confused how it is working fine when using single Data source

Unhandled async exception in Resource with Server-Sent Event RESTEasy + Spring Integracion

The Task: The API is built using JAX-RS RESTEasy and Spring(RESTEasy-Spring Dependency) in order to enable API to use Spring dependency injection features, and also . Here everything is working fine. Then, In a resource there is a method to send messages from a server to the client in real-time(Server-Sent Event). I took this code(enter link description here) to build the method, but in the example EJB is used and some concurrency annotation defined there(#Singleton, #LOCK, LockType.{READ,WRITE}).
The Problem: When I consume that method the server throw the following exception:
20:15:29,669 ERROR [org.jboss.resteasy.resteasy_jaxrs.i18n] (default task-1) RESTEASY002020: Unhandled asynchronous exception, sending back 500: org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException
I guest the problem is related to concurrency. First, the application was standalone(RUNNING ON JETTY), then it was deployed on wildfly application server in order to use EJB features and replicate the same example. However, due to the fact I use RESTEasy + Spring the resource(JAX-RS Resource) has to be annotated with #Component and managed by Spring Container. I tried to replace that with EJB #Singleton annotation and use #Lock() annotation in the methods as well, but when that is done the resource is not found(not deploy). I guest it is required the resource to be annotated with #Component in order to get this integration(RESTEasy + Spring) working. I searched about concurrency with Java SE and made use of the following package java.util.concurrent.locks but with no success.
These are my interface and class:
package edu.cibertec.votoelectronico.resource;
import java.io.IOException;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.sse.SseEventSink;
import org.springframework.context.event.EventListener;
import edu.cibertec.votoelectronico.application.event.EmitirVotoEvent;
#Path("/votoelectronico/subscribe")
public interface SSEVotoElectronicoResource {
#GET
#Lock(LockType.READ)
#Path("/resultado")
#Produces(MediaType.SERVER_SENT_EVENTS)
public void obtenerResultados(#HeaderParam(HttpHeaders.LAST_EVENT_ID_HEADER) #DefaultValue("-1") int lastEventId,
#Context SseEventSink eventSink) throws IOException;
#Lock(LockType.WRITE)
#EventListener
public void onEmitirVotoEvent(EmitirVotoEvent domainEvent);
#GET
#Path("/")
#Produces(MediaType.APPLICATION_JSON)
public Response test();
}
package edu.cibertec.votoelectronico.resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
//import javax.ejb.Lock;
//import javax.ejb.LockType;
//import javax.ejb.Singleton;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.sse.OutboundSseEvent;
import javax.ws.rs.sse.Sse;
import javax.ws.rs.sse.SseBroadcaster;
import javax.ws.rs.sse.SseEventSink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import edu.cibertec.votoelectronico.application.event.EmitirVotoEvent;
import edu.cibertec.votoelectronico.domain.complex.VotoResumen;
import edu.cibertec.votoelectronico.dto.VotoResumenDto;
import edu.cibertec.votoelectronico.mapping.MapperFactoryRegistry;
import edu.cibertec.votoelectronico.resource.communication.BaseResponse;
import edu.cibertec.votoelectronico.resource.communication.ResumenProcesoResponse;
import edu.cibertec.votoelectronico.service.VotoService;
//#Singleton
#Path("/votoelectronico/subscribe")
#Component
public class SimpleSSEVotoElectronicoResource implements SSEVotoElectronicoResource {
private final Logger LOG = LoggerFactory.getLogger(SimpleSSEVotoElectronicoResource.class);
private Sse sse;
private final Lock readLock;
private final Lock writeLock;
#Autowired
private VotoService service;
#Autowired
private MapperFactoryRegistry mapper;
private SseBroadcaster sseBroadcaster;
private int lastEventId;
private final List<ResumenProcesoResponse> messages = new ArrayList<ResumenProcesoResponse>();
public SimpleSSEVotoElectronicoResource() {
ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
this.readLock = readWriteLock.readLock();
this.writeLock = readWriteLock.writeLock();
}
#PostConstruct
public void init() {
LOG.info("On Init method...");
}
#Context
public void setSse(Sse sse) {
this.sse = sse;
this.sseBroadcaster = this.sse.newBroadcaster();
this.sseBroadcaster.onError((o, e) -> {
LOG.error("Ocurred an error on broadcasting: ", e);
});
this.sseBroadcaster.onClose((eventSink) -> {
LOG.info("Broadcast closed: ", eventSink);
});
}
#Override
// #Lock(LockType.READ)
public void obtenerResultados(int lastEventId, SseEventSink eventSink) throws IOException {
readLock.lock();
try {
if (lastEventId >= 0)
this.replyLastMessage(lastEventId, eventSink);
sseBroadcaster.register(eventSink);
LOG.info("Client has being registered");
} finally {
readLock.unlock();
}
}
#Override
// #Lock(LockType.WRITE)
public void onEmitirVotoEvent(EmitirVotoEvent domainEvent) {
writeLock.lock();
try {
LOG.info("EmitirVoto Event received");
ResumenProcesoResponse response = this.fetchResumenProceso();
this.messages.add(response);
OutboundSseEvent event = createEvent(response, ++this.lastEventId);
LOG.info("Server about to send Event");
this.sseBroadcaster.broadcast(event);
} finally {
writeLock.unlock();
}
}
private void replyLastMessage(int lastEventId, SseEventSink eventSink) {
try {
for (int i = lastEventId; i < messages.size(); i++) {
eventSink.send(createEvent(messages.get(i), i + 1));
}
} catch (Exception e) {
throw new InternalServerErrorException("Could not reply messages ", e);
}
}
private ResumenProcesoResponse fetchResumenProceso() {
ResumenProcesoResponse response = null;
try {
LOG.info("Fetching proccess resume..");
Collection<VotoResumen> resultados = this.service.results();
Function<VotoResumen, VotoResumenDto> convert = (VotoResumen object) -> this.mapper.convertFrom(object,
VotoResumenDto.class);
Collection<VotoResumenDto> collection = resultados.stream().map(convert).collect(Collectors.toList());
response = new ResumenProcesoResponse(collection);
} catch (Exception e) {
LOG.error("Ocurred an error while trying to get resume. " + e.getMessage());
response = new ResumenProcesoResponse(e.getMessage());
}
return response;
}
private OutboundSseEvent createEvent(ResumenProcesoResponse response, int id) {
return this.sse.newEventBuilder().id(String.valueOf(id)).data(response).build();
}
#Override
public Response test() {
try {
return Response.status(Response.Status.OK).entity(new BaseResponse(true, "")).build();
} catch (Exception e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(new BaseResponse(false, e.toString()))
.build();
}
}
}
Full error description:
20:15:29,669 ERROR [org.jboss.resteasy.resteasy_jaxrs.i18n] (default task-1) RESTEASY002020: Unhandled asynchronous exception, sending back 500: org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException
at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:82)
at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:346)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:193)
at org.jboss.resteasy.core.SynchronousDispatcher.asynchronousExceptionDelivery(SynchronousDispatcher.java:510)
at org.jboss.resteasy.core.AbstractAsynchronousResponse.internalResume(AbstractAsynchronousResponse.java:232)
at org.jboss.resteasy.plugins.server.servlet.Servlet3AsyncHttpRequest$Servlet3ExecutionContext$Servle3AsychronousResponse.resume(Servlet3AsyncHttpRequest.java:117)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:431)
at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$0(ResourceMethodInvoker.java:370)
at org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:356)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:372)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:344)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:317)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:440)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:229)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:135)
at org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:356)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:138)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:215)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:227)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
at io.opentracing.contrib.jaxrs2.server.SpanFinishingFilter.doFilter(SpanFinishingFilter.java:52)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:376)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
at edu.cibertec.votoelectronico.resource.SimpleSSEVotoElectronicoResource.obtenerResultados(SimpleSSEVotoElectronicoResource.java:90)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:138)
at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:517)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:406)
... 63 more
Example code:
package com.example.sse.boundary;
import com.example.sse.entity.DomainEvent;
import javax.annotation.PostConstruct;
import javax.ejb.Lock;
import javax.ejb.Singleton;
import javax.enterprise.event.Observes;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.sse.OutboundSseEvent;
import javax.ws.rs.sse.Sse;
import javax.ws.rs.sse.SseBroadcaster;
import javax.ws.rs.sse.SseEventSink;
import java.util.ArrayList;
import java.util.List;
import static javax.ejb.LockType.READ;
import static javax.ejb.LockType.WRITE;
#Path("events-examples")
#Singleton
public class EventsResource {
#Context
Sse sse;
private SseBroadcaster sseBroadcaster;
private int lastEventId;
private List<String> messages = new ArrayList<>();
#PostConstruct
public void initSse() {
sseBroadcaster = sse.newBroadcaster();
sseBroadcaster.onError((o, e) -> {
// ...
});
}
#GET
#Lock(READ)
#Produces(MediaType.SERVER_SENT_EVENTS)
public void itemEvents(#HeaderParam(HttpHeaders.LAST_EVENT_ID_HEADER)
#DefaultValue("-1") int lastEventId,
#Context SseEventSink eventSink) {
if (lastEventId >= 0)
replayLastMessages(lastEventId, eventSink);
sseBroadcaster.register(eventSink);
}
private void replayLastMessages(int lastEventId, SseEventSink eventSink) {
try {
for (int i = lastEventId; i < messages.size(); i++) {
eventSink.send(createEvent(messages.get(i), i + 1));
}
} catch (Exception e) {
throw new InternalServerErrorException("Could not replay messages ", e);
}
}
private OutboundSseEvent createEvent(String message, int id) {
return sse.newEventBuilder().id(String.valueOf(id)).data(message).build();
}
#Lock(WRITE)
public void onEvent(#Observes DomainEvent domainEvent) {
String message = domainEvent.getContents();
messages.add(message);
OutboundSseEvent event = createEvent(message, ++lastEventId);
sseBroadcaster.broadcast(event);
}
}
The source code is here: enter link description here
I tried to catch the error but with no success.
Can you please help me out to solve this error or give some advices.

Spring CRUD App: Servlet.service() for servlet [dispatcherServlet] : java.lang.NullPointerException]

I've a problem to get employees data from mySQL db. According to logs there is a problem at line: 36 in my EmployeeServiceImpl.listEmployess metod.
Logs:
2018-10-18 16:07:42.871 ERROR 1504 --- [nio-8090-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
at com.project.service.EmployeeServiceImpl.listEmployess(EmployeeServiceImpl.java:36) ~[classes/:na]
com.project.service.EmployeeServiceImpl$$FastClassBySpringCGLIB$$c7d76ecc.invoke() ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at com.project.service.EmployeeServiceImpl$$EnhancerBySpringCGLIB$$1390ca06.listEmployess() ~[classes/:na]
at com.project.controller.EmployeeController.listEmployess(EmployeeController.java:34) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
EmployeeServiceImpl:
package com.project.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.project.dao.EmployeeDAO;
import com.project.entity.TEmployee;
#Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService {
private EmployeeDAO employeeDAO;
public void setEmployeeDAO(EmployeeDAO employeeDAO) {
this.employeeDAO = employeeDAO;
}
#Override
#Transactional
public void addEmployee(TEmployee p) {
this.employeeDAO.addEmployee(p);
}
#Override
#Transactional
public void updateEmployee(TEmployee p) {
this.employeeDAO.updateEmployee(p);
}
#Override
#Transactional
public List<TEmployee> listEmployess() {
return this.employeeDAO.listEmployess();
}
#Override
#Transactional
public TEmployee getEmployeeById(int employee_id) {
return this.employeeDAO.getEmployeeById(employee_id);
}
#Override
#Transactional
public void removeEmployee(int employee_id) {
this.employeeDAO.removeEmployee(employee_id);
}
}
EmployeeService:
package com.project.service;
import java.util.List;
import org.springframework.context.annotation.ComponentScan;
import com.project.entity.TEmployee;
#ComponentScan(basePackages= {"com.project.*"})
public interface EmployeeService {
public void addEmployee(TEmployee p);
public void updateEmployee(TEmployee p);
public List<TEmployee> listEmployess();
public TEmployee getEmployeeById(int id);
public void removeEmployee(int id);
}
EmployeeDAO:
package com.project.dao;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import com.project.entity.TEmployee;
#ComponentScan(basePackages= {"com.project.*"})
public interface EmployeeDAO {
public void addEmployee(TEmployee p);
public void updateEmployee(TEmployee p);
public List<TEmployee> listEmployess();
public TEmployee getEmployeeById(int employee_id);
public void removeEmployee(int employee_id);
}
EmployeeDAOImpl:
package com.project.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.project.entity.TEmployee;
#Repository
public class EmployeeDAOImpl implements EmployeeDAO {
private static final Logger logger = LoggerFactory.getLogger(EmployeeDAOImpl.class);
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
this.sessionFactory = sf;
}
#Override
public void addEmployee(TEmployee p) {
Session session = this.sessionFactory.getCurrentSession();
session.persist(p);
logger.info("TEmployee saved successfully, TEmployee Details="+p);
}
#Override
public void updateEmployee(TEmployee p) {
Session session = this.sessionFactory.getCurrentSession();
session.update(p);
logger.info("TEmployee updated successfully, TEmployee Details="+p);
}
#SuppressWarnings("unchecked")
#Override
public List<TEmployee> listEmployess() {
Session session = this.sessionFactory.getCurrentSession();
List<TEmployee> EmployessList = session.createQuery("from TEmployee").list();
for(TEmployee p : EmployessList){
logger.info("TEmployee List::"+p);
}
return EmployessList;
}
#Override
public TEmployee getEmployeeById(int employee_id) {
Session session = this.sessionFactory.getCurrentSession();
TEmployee p = (TEmployee) session.load(TEmployee.class, new Integer(employee_id));
logger.info("TEmployee loaded successfully, TEmployee details="+p);
return p;
}
#Override
public void removeEmployee(int employee_id) {
Session session = this.sessionFactory.getCurrentSession();
TEmployee p = (TEmployee) session.load(TEmployee.class, new Integer(employee_id));
if(null != p){
session.delete(p);
}
logger.info("TEmployee deleted successfully, TEmployee details="+p);
}
}
And EmployeeController:
package com.project.controller;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.project.entity.TEmployee;
import com.project.service.EmployeeService;
#ComponentScan(basePackages= {"com.project.*"})
#Controller
public class EmployeeController {
#Resource(name = "employeeService")
private EmployeeService employeeService;
#Autowired(required=true)
#Qualifier(value="employeeService")
public void setEmployeeService(EmployeeService ps){
this.employeeService = ps;
}
#RequestMapping(value = "/employess", method = RequestMethod.GET)
public String listEmployess(Model model) {
model.addAttribute("employee", new TEmployee());
model.addAttribute("listEmployess", this.employeeService.listEmployess());
return "employee";
}
//For add and update person both
#RequestMapping(value= "/employee/add", method = RequestMethod.POST)
public String addEmployee(#ModelAttribute("employee") TEmployee p){
if(p.getEmployeeID() == 0){
//new person, add it
this.employeeService.addEmployee(p);
}else{
//existing person, call update
this.employeeService.updateEmployee(p);
}
return "redirect:/employess";
}
#RequestMapping("/remove/{employee_id}")
public String removeEmployee(#PathVariable("employee_id") int employee_id){
this.employeeService.removeEmployee(employee_id);
return "redirect:/employess";
}
#RequestMapping("/edit/{employee_id}")
public String editEmployee(#PathVariable("employee_id") int employee_id, Model model){
model.addAttribute("employee", this.employeeService.getEmployeeById(employee_id));
model.addAttribute("listEmployess", this.employeeService.listEmployess());
return "employee";
}
}
So, according to logs there is a NPE returning from this line:
return this.employeeDAO.listEmployess();
Do you have any idea what could be wrong here?
Thanks in advance!
Hi instead of setter method use Autowired annotation on dependency private EmployeeDAO employeeDAO;
like
#Autowired
private EmployeeDAO employeeDAO;

400 Bad Request using RestTemplete and postForObject

i'm building two applications using Spring 3.The first one is meant to be rest API and the second is a client.The client must create a reservation. I'm getting 400 Bad Request error,please help.
The class Reservation in the client app:
package ma.ensias.agencecentrale.entities;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;
#JsonIgnoreProperties(ignoreUnknown=true)
#Entity
#Table(name="reservations")
public class Reservation implements Serializable{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long idReservation;
private String date;
#ManyToOne
#JoinColumn(name="id_utilisateur")
private Utilisateur utilisateur;
#JsonIgnore
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(name="passager_reservation", joinColumns=#JoinColumn(name="id_reservation"), inverseJoinColumns=#JoinColumn(name="id_passager"))
private Collection<Passager> passagers;
#JsonIgnore
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(name="vol_reservation", joinColumns=#JoinColumn(name="id_reservation"), inverseJoinColumns=#JoinColumn(name="id_vol"))
private Collection<Vol> vols;
// Contructor without fields
public Reservation() {
super();
}
// contructor with date attribute
public Reservation(String date) {
super();
this.date = date;
}
// ----------------------- Getters and setters-------------------------------
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
#JsonProperty(value="client")
public Utilisateur getUtilisateur() {
return utilisateur;
}
public void setUtilisateur(Utilisateur utilisateur) {
this.utilisateur = utilisateur;
}
public Collection<Vol> getVols() {
return vols;
}
public void setVols(Collection<Vol> vols) {
this.vols = vols;
}
public Long getIdReservation() {
return idReservation;
}
}
the rest Client :
//-------------------Create a Reservation--------------------------------------------------------
#RequestMapping("/ajouterReservation")
private static void ajouterReservation(Reservation reservation) {
RestTemplate restTemplate = new RestTemplate();
Reservation addedRes = restTemplate.postForObject(REST_SERVICE_URI,reservation, Reservation.class);
}
And the class Reservation in provider app:
package ma.ensias.agencevoyage.entities;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;
#JsonIgnoreProperties(ignoreUnknown=true)
#Entity
#Table(name="reservations")
public class Reservation implements Serializable{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long idReservation;
private String date;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name="id_client")
private Client client;
#JsonIgnore
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(name="passager_reservation", joinColumns=#JoinColumn(name="id_reservation"), inverseJoinColumns=#JoinColumn(name="id_passager"))
private Collection<Passager> passagers;
#JsonIgnore
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(name="vol_reservation", joinColumns=#JoinColumn(name="id_reservation"), inverseJoinColumns=#JoinColumn(name="id_vol"))
private Collection<Vol> vols;
// Contructor without fields
public Reservation() {
super();
}
// contructor with date attribute
public Reservation(String date) {
super();
this.date = date;
}
// ----------------------- Getters and setters-------------------------------
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public Collection<Passager> getPassagers() {
return passagers;
}
public void setPassagers(Collection<Passager> passagers) {
this.passagers = passagers;
}
public Collection<Vol> getVols() {
return vols;
}
public void setVols(Collection<Vol> vols) {
this.vols = vols;
}
}
and the controller is :
//-------------------Create a Reservation--------------------------------------------------------
#RequestMapping(value = "/ajouterReservation", method = RequestMethod.POST, consumes="application/json")
public ResponseEntity<String> ajouterReservation(#RequestBody Reservation reservation) {
metier.ajouterReservation(reservation);
return new ResponseEntity(HttpStatus.CREATED);
}
I also tested the provider using post man and it is working.
The error i'm getting is below :
GRAVE: Servlet.service() for servlet [appServlet] in context with path [/agencecentrale] threw exception [Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 415 Type de Support Non Supporté] with root cause
org.springframework.web.client.HttpClientErrorException: 415 Type de Support Non Supporté
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:88)
at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:532)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:488)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:446)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:294)
at ma.ensias.agencecentrale.controllers.ReservationController.ajouterReservation(ReservationController.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:958)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:452)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1087)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
Root cause : Problem is with content type set in the provider controller:
#RequestMapping(value = "/ajouterReservation", method = RequestMethod.POST, consumes="application/json")
public ResponseEntity<String> ajouterReservation(#RequestBody Reservation reservation)
Solution 1: remove consumes="application/json" in the handler method
Solution 2 : Set the headers accordingly before making the rest call and make use of exchange method of RestTemplate like below :
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers=new HttpHeaders();
headers.set("Content-Type", "application/json");
HttpEntity requestEntity=new HttpEntity(reservation, headers);
Reservation addedRes = restTemplate.exchange(REST_SERVICE_URI, HttpMethod.POST,requestEntity,Reservation.class);

Resources