I'm trying to migrate from Spring XML based configuration to Pure Java Configuration, I have configured all the configuration files, but when I try to enter the username and password in login page, it redirects me back to the login page again. I believe the userServiceImpl method is not being invoked because the control is not going there.
Here, I have autowired userServiceImpl method which is implementing UserDetailsService of spring security core credentials.
package com.lw.sms.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.lw.sms.CustomAuthenticationSuccessHandler;
import com.lw.sms.UserServiceImpl;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
#EnableTransactionManagement
#Order(1000)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
#Value("${jdbc.dialect}")
String jdbcDialect;
#Value("${jdbc.driverClassName}")
String jdbcDriverClassName;
#Value("${jdbc.databaseurl}")
String jdbcDatabaseurl;
#Value("${jdbc.username}")
String jdbcusername;
#Value("${jdbc.password}")
String jdbcPassword;
#Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
#Autowired
private UserServiceImpl userServiceImpl;
#Override
public void configure(final AuthenticationManagerBuilder auth) throws Exception {
logger.info("configure auth");
auth.userDetailsService(userServiceImpl);
}
#Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
#Override
public void configure(HttpSecurity http) throws Exception {
logger.info("configure http");
http.httpBasic().disable();
http.authorizeRequests().and().formLogin().loginPage("/login").usernameParameter("employeeId")
.passwordParameter("password").successHandler(customAuthenticationSuccessHandler)
.failureUrl("/login?error").defaultSuccessUrl("/dashboard", true)
.loginProcessingUrl("j_spring_security_check")
.and().logout().logoutUrl("/j_spring_security_logout").logoutSuccessUrl("/logout")
.invalidateHttpSession(true).deleteCookies("JSESSIONID")
.and().sessionManagement().invalidSessionUrl("/logout").maximumSessions(1)
.maxSessionsPreventsLogin(true).expiredUrl("/logout");
http.csrf().disable();
http.authorizeRequests().anyRequest().authenticated();
}
#Bean
public SessionRegistry sessionRegistry() {
logger.info("sessionRegistry");
return new SessionRegistryImpl();
}
#Bean
public SessionFactory sessionFactory() {
LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource());
builder.scanPackages("com.lw.sms").addProperties(hibernateProperties());
return builder.buildSessionFactory();
}
#Bean
public LocalSessionFactoryBean hibernateSessionFactory() {
logger.info("sessionFactory");
org.hibernate.cfg.Configuration configuration = new org.hibernate.cfg.Configuration();
configuration.configure("hibernate.cfg.xml");
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan("com.lw.sms");
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
logger.info("dataSource");
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(jdbcDriverClassName);
dataSource.setUrl(jdbcDatabaseurl);
dataSource.setUsername(jdbcusername);
dataSource.setPassword(jdbcPassword);
return dataSource;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
logger.info("transactionManager");
HibernateTransactionManager htm = new HibernateTransactionManager();
htm.setSessionFactory(sessionFactory);
return htm;
}
#Bean
public Properties hibernateProperties() {
logger.info("hibernateProperties");
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.show_sql", "true");
hibernateProperties.setProperty("hibernate.dialect", jdbcDialect);
hibernateProperties.setProperty("hibernate.default_schema", "sms");
return hibernateProperties;
}
}
CustomAuthenticationSuccessHandler Code is attached below
package com.lw.sms;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;
import com.lw.sms.constants.Constants;
import com.lw.sms.user.entities.EmployeeEntity;
import com.lw.sms.user.entities.EmployeePermissionsEntity;
import com.lw.sms.user.service.UserManagementService;
import com.lw.sms.util.QueryBuilder;
#Component("customAuthenticationSuccessHandler")
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private static final Logger logger = LoggerFactory.getLogger(CustomAuthenticationSuccessHandler.class);
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
#Autowired
#Qualifier("sessionInfo")
private SessionInfo sessionInfo;
#Autowired
#Qualifier("userManagementServiceImpl")
private UserManagementService userManagementService;
#Autowired
private HttpServletRequest httpServletRequest;
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException {
response.setStatus(HttpServletResponse.SC_OK);
clearAuthenticationAttributes(request);
handle(request, response);
}
protected void handle(HttpServletRequest request, HttpServletResponse response)
throws IOException {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
EmployeeEntity employeeEntity = (EmployeeEntity) principal;
setSessionInformationForEmployee(employeeEntity);
}
if (response.isCommitted()) {
return;
}
startServices();
redirectStrategy.sendRedirect(request, response, "/dashboard");
}
/**
* #param employeeEntity
*
*/
private void setSessionInformationForEmployee(EmployeeEntity employeeEntity) {
try {
WebAuthenticationDetails details = (WebAuthenticationDetails) SecurityContextHolder.getContext()
.getAuthentication().getDetails();
userManagementService.updateLoginInfo(employeeEntity.getUsername(), details.getRemoteAddress());
// setting session information
} catch (Exception e) {
logger.info("Exception while set Session Information For Employee :" + ExceptionUtils.getFullStackTrace(e));
}
}
private void startServices() {
logger.info("Starting Services..");
try {
String domainName = httpServletRequest.getScheme() + "://" + httpServletRequest.getServerName();
if (httpServletRequest.getServerPort() != 0) {
domainName += ":" + httpServletRequest.getServerPort();
}
domainName += httpServletRequest.getContextPath();
Constants.domainName = domainName + "/resources";
} catch (Exception e) {
logger.error("Error in start services :"+ ExceptionUtils.getFullStackTrace(e));
}
}
protected void clearAuthenticationAttributes(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) {
return;
}
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
}
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
this.redirectStrategy = redirectStrategy;
}
protected RedirectStrategy getRedirectStrategy() {
return redirectStrategy;
}
}
UserServiceImpl Code is attached below
package com.lw.sms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.lw.sms.user.dao.UserManagementDAO;
import com.lw.sms.user.entities.EmployeeEntity;
#Service("userServiceImpl")
public class UserServiceImpl implements UserDetailsService {
#Autowired
#Qualifier("userManagementDAOImpl")
private UserManagementDAO userManagementDAO;
#Override
#Transactional
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
EmployeeEntity employeeEntity = userManagementDAO.loadUserByUsername(username);
if (employeeEntity == null) {
ContractorEntity contractorEntity = userManagementDAO.loadUserByUsernameContractor(username);
if(contractorEntity == null)
throw new AuthenticationCredentialsNotFoundException("Invalid Username or Password");
}
if(!employeeEntity.isEnabled())
throw new AuthenticationCredentialsNotFoundException("Employee Disabled");
return employeeEntity;
}
}
Global Exception Handler Code:
package com.lw.sms;
import java.io.IOException;
import java.nio.charset.Charset;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.stereotype.Controller;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.HttpSessionRequiredException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
#SuppressWarnings("deprecation")
#Controller
#ControllerAdvice
public class CustomExceptionHandler extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 3699167829164697594L;
private static final Logger logger = LoggerFactory
.getLogger(CustomExceptionHandler.class);
#ExceptionHandler(AuthenticationCredentialsNotFoundException.class)
#ResponseStatus(HttpStatus.UNAUTHORIZED)
public ModelAndView handleLoginExceptions(HttpServletRequest request,
HttpServletResponse response,Exception exception) {
logger.info("Handling exception time error"+ exception.getMessage());
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("login");
return modelAndView;
}
#ExceptionHandler(HttpSessionRequiredException.class)
public String handleSessionExpired() {
logger.info("session-expired");
return "logout";
}
#SuppressWarnings("unchecked")
#ExceptionHandler(value = { MissingServletRequestParameterException.class,
ServletRequestBindingException.class, TypeMismatchException.class,
HttpMessageNotReadableException.class,
MethodArgumentNotValidException.class,
MissingServletRequestPartException.class })
#ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "Bad Request")
#ResponseBody
public JSONObject handle400Exception(Exception ex,HttpServletResponse response) {
logger.error("400 Exception" + ex.getMessage());
JSONObject jsonObject=new JSONObject();
jsonObject.put("status", HttpStatus.BAD_REQUEST);
jsonObject.put("success", false);
jsonObject.put("message", ex.getMessage());
try {
response.getOutputStream().write(jsonObject.toString().getBytes(Charset.defaultCharset()));
} catch (IOException e) {
logger.error(ExceptionUtils.getFullStackTrace(e));
}
response.setContentType("application/json; charset=UTF-8");
return jsonObject;
}
#ExceptionHandler(value = { NoSuchRequestHandlingMethodException.class, })
#ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Not Found")
#ResponseBody
public Boolean handle404Exception(Exception ex) {
logger.error("404 Exception" + ExceptionUtils.getFullStackTrace(ex));
return false;
}
#ExceptionHandler(value = { HttpRequestMethodNotSupportedException.class,
HttpMediaTypeNotSupportedException.class })
#ResponseStatus(value = HttpStatus.NOT_ACCEPTABLE, reason = "Not Supported")
#ResponseBody
public Boolean handle405Exception(Exception ex) {
logger.error("405 Exception" + ExceptionUtils.getFullStackTrace(ex));
return false;
}
#ExceptionHandler(value = { HttpMessageNotWritableException.class,
ConversionNotSupportedException.class })
#ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR, reason = "Internal Server Error")
#ResponseBody
public Boolean handle500Exception(Exception ex) {
logger.error("500 Exception" + ExceptionUtils.getFullStackTrace(ex));
return false;
}
#ExceptionHandler({ Exception.class })
public ModelAndView handleException(Exception ex, HttpServletRequest request,
HttpServletResponse response) {
logger.info("*****************************************************");
logger.error("Exception: " + ExceptionUtils.getFullStackTrace(ex));
ex.printStackTrace();
logger.info("*****************************************************");
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("logout");
return modelAndView;
}
}
This is my HomeController.
package com.lw.sms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import com.lw.sms.master.service.MasterDataService;
import com.lw.sms.user.entities.EmployeeEntity;
/**
* Handles requests for the application home page.
*/
#Controller("homeController")
public class HomeController {
#Autowired
#Qualifier("masterDataServiceImpl")
private MasterDataService masterDataService;
#Autowired
#Qualifier("sessionInfo")
private SessionInfo sessionInfo;
#GetMapping(value = { "/home", "/", "login" })
public ModelAndView home() {
return new ModelAndView("login");
}
#GetMapping(value = "dashboard")
public ModelAndView dashboard() {
EmployeeEntity user = sessionInfo.getEmployeeEntity();
return new ModelAndView("dashboard", "userDetails", user);
}
// Logout page
#ResponseStatus(code = HttpStatus.UNAUTHORIZED)
#GetMapping(value = "logout")
public String logout() {
return "logout";
}
}
Could you please try adding the successForwardUrl also as below.
http.authorizeRequests().antMatchers("/login").permitAll()
.antMatchers("/dashboard").access("IS_AUTHENTICATED_FULLY")
.antMatchers("/j_spring_security_check").access("IS_AUTHENTICATED_ANONYMOUSLY")
.and().formLogin().loginPage("/login").usernameParameter("employeeId").passwordParameter("password")
.successForwardUrl("/dashboard").defaultSuccessUrl("/dashboard", true).failureForwardUrl("/loginfailed")
.loginProcessingUrl("/j_spring_security_check")
.and().logout().logoutSuccessUrl("/logout").invalidateHttpSession(true)
.and().sessionManagement().sessionFixation().none()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/login")
.and().exceptionHandling().accessDeniedPage("/Access_Denied").and().csrf().disable();
I was able to replicate the error.
I had to configure a new bean in SecurityConfig file.
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userServiceImpl);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
Related
This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 3 years ago.
In my application I have autowired dataSource object which is being returned null.
The object is being used in DAO class.
Application Flow ->
1.OAConsumer.java starts execution
2. calls service.java
3. calls insertOffset in KafkaDAOImpl class
IDE used in eclispe Oxygen.
Code and error details below.
Error shown
java.lang.NullPointerException
at com.oa.dao.KafkaOffsetDAOImpl.insertOffset(KafkaOffsetDAOImpl.java:36)
at com.oa.services.Service.savePayload(Service.java:54)
at com.oa.consumer.OAConsumer.orderConsumer(OAConsumer.java:30)
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.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:170)
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:120)
at org.springframework.kafka.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:48)
at org.springframework.kafka.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:283)
at org.springframework.kafka.listener.adapter.BatchMessagingMessageListenerAdapter.invoke(BatchMessagingMessageListenerAdapter.java:146)
at org.springframework.kafka.listener.adapter.BatchMessagingMessageListenerAdapter.onMessage(BatchMessagingMessageListenerAdapter.java:138)
at org.springframework.kafka.listener.adapter.BatchMessagingMessageListenerAdapter.onMessage(BatchMessagingMessageListenerAdapter.java:59)
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeBatchOnMessage(KafkaMessageListenerContainer.java:1052)
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeBatchOnMessage(KafkaMessageListenerContainer.java:1036)
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeBatchListener(KafkaMessageListenerContainer.java:998)
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeBatchListener(KafkaMessageListenerContainer.java:938)
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeListener(KafkaMessageListenerContainer.java:921)
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.pollAndInvoke(KafkaMessageListenerContainer.java:740)
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.run(KafkaMessageListenerContainer.java:689)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
KafkaOffsetDAOImpl.java
package com.oa.dao;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import com.oa.model.KafkaOffsetRecord;
public class KafkaOffsetDAOImpl implements KafkaOffsetDAO {
// #Autowired
// JdbcTemplate jdbcTemplate;
#Autowired
DataSource dataSource;
#Override
public boolean insertOffset(KafkaOffsetRecord offsetRecord) {
boolean status=false;
try(Connection connection =dataSource.getConnection()){
if(connection.isValid(10000))
status= true;
}catch (Exception e) {
e.printStackTrace();
}
return false;
}
OracleConfig.java
package com.oa.config;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
#Configuration
public class OracleConfig {
private static final Logger logger = LoggerFactory.getLogger(OracleConfig.class);
#Value("${spring.datasource.url}")
private String url;
#Value("${spring.datasource.username}")
private String username;
#Value("${spring.datasource.password}")
private String password;
#Value("${spring.datasource.driver-class-name}")
private String driverClassName;
#Value("${spring.datasource.maximumPoolSize}")
private int maxPoolSize;
#Value("${spring.datasource.minimumIdle}")
private int minIdle;
#Value("${spring.datasource.connectionTimeout}")
private long connTimeOut;
#Value("${spring.datasource.idleTimeout}")
private long idleTimeout;
//
/**
* See http://www.baeldung.com/hikaricp
*/
#Bean
public HikariDataSource dataSource() {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName(driverClassName);
hikariConfig.setUsername(username);
hikariConfig.setPassword(password);
hikariConfig.setJdbcUrl(url);
hikariConfig.setMaximumPoolSize(maxPoolSize);
hikariConfig.setConnectionTimeout(connTimeOut);
hikariConfig.setMinimumIdle(minIdle);
hikariConfig.setIdleTimeout(idleTimeout);
HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);
if (hikariDataSource.isRunning()) {
logger.info("------> Oracle DB connection created successfully.");
}
return hikariDataSource;
}
Consumer.java
package com.oa.consumer;
import java.util.List;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.kafka.support.KafkaHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Payload;
import com.oa.services.OrderService;
public class OAConsumer {
private static final Logger LOGGER = LoggerFactory.getLogger(OAConsumer.class);
#KafkaListener(topics = "**removed**", groupId = "**removed**")
public void orderConsumer(List<ConsumerRecord<String, String>> records, Acknowledgment acknowledgment) {
LOGGER.debug("START :: orderConsumer");
OrderService orderService = new OrderService();
try {
for (ConsumerRecord<String, String> record : records) {
LOGGER.debug("Processing Offset Order :: offset={} :: partitionId={} :: topicName={}", record.offset(),
record.partition(), record.topic());
orderService.savePayload(record);
}
acknowledgment.acknowledge();
LOGGER.debug("END :: orderConsumer:: Acknowledged");
} catch (Exception exception) {
exception.printStackTrace();
LOGGER.error(exception.getMessage());
}
}
Service.java
package com.oa.services;
import java.io.IOException;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.oa.dao.KafkaOffsetDAO;
import com.oa.dao.KafkaOffsetDAOImpl;
import com.oa.model.KafkaOffsetRecord;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Service {
private static final Logger LOGGER = LoggerFactory.getLogger(Service.class);
public Boolean checkOAEligible(String message, long offset, String topic) throws IOException {
return true;
}
public Boolean savePayload(ConsumerRecord<String, String> record) {
LOGGER.debug("START:: saveOrderPayload ::offset= {} :: topic= {}", record.offset(), record.topic());
Boolean status = false;
KafkaOffsetDAO dao = new KafkaOffsetDAOImpl();
try {
if (checkOAEligible(record.value(), record.offset(), record.topic())) {
KafkaOffsetRecord kafkaOffsetRecord= new KafkaOffsetRecord(record);
status = dao.insertOffset(kafkaOffsetRecord);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
LOGGER.debug("END:: saveOrderPayload :: offset={} :: topic={} , status={}", record.offset(), record.topic(), status);
return status;
}
}
KafkaOffsetRecord
package com.oa.model;
import org.apache.kafka.clients.consumer.ConsumerRecord;
public class KafkaOffsetRecord {
long offsetId;
String jsonMsg;
String kafkaSourceType;
int partitionId;
String kafkaTopicName;
public KafkaOffsetRecord() {
}
public KafkaOffsetRecord(ConsumerRecord<String, String> consumerRecord) {
offsetId = consumerRecord.offset();
jsonMsg = consumerRecord.value();
partitionId=consumerRecord.partition();
kafkaTopicName= consumerRecord.topic();
kafkaSourceType = "TEST";
}
public long getOffsetId() {
return offsetId;
}
public String getJsonMsg() {
return jsonMsg;
}
public String getKafkaSourceType() {
return kafkaSourceType;
}
public int getPartitionId() {
return partitionId;
}
public String getKafkaTopicName() {
return kafkaTopicName;
}
public void setOffsetId(long offsetId) {
this.offsetId = offsetId;
}
public void setJsonMsg(String jsonMsg) {
this.jsonMsg = jsonMsg;
}
public void setKafkaSourceType(String kafkaSourceType) {
this.kafkaSourceType = kafkaSourceType;
}
public void setPartitionId(int partitionId) {
this.partitionId = partitionId;
}
public void setKafkaTopicName(String kafkaTopicName) {
this.kafkaTopicName = kafkaTopicName;
}
}
application.properties
spring.datasource.url=jdbc:oracle:thin:#(DESCRIPTION=(ADDRESS_LIST=(LOAD_BALANCE=ON)(FAILOVER=OFF)(ADDRESS=(PROTOCOL=TCP)(HOST=**removed**)(PORT=**removed**))(ADDRESS=(PROTOCOL=TCP)(HOST=**removed**)(PORT=**removed**)))(CONNECT_DATA=(SERVICE_NAME=**removed**)(SERVER=DEDICATED)))
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.username=**removed**
spring.datasource.password=**removed**
spring.datasource.type=oracle.jdbc.pool.OracleDataSource
spring.datasource.maximumPoolSize=20
spring.datasource.minimumIdle=5
spring.datasource.connectionTimeout=30000
spring.datasource.idleTimeout=1500000
use constructor injection, when you use it
public class KafkaOffsetDAOImpl implements KafkaOffsetDAO {
private final DataSource dataSource;
#Autowired
KafkaOffsetDAOImpl(final Datasource datasrouce) {
this.dataSource = dataSource;
}
this way you can be sure, that spring creates the autowired field and injects it.
How to implement JWT based authentication and authorization in Spring Security
I am trying to implement jwt based authentication and authorization in my spring boot app. I followed a tutorial written here. But it does not do anything in my app. It does not return jwt token rather I am authenticated and my request is fulfilled. I am new to spring security. here is my code.
I want my app return jwt token and using the token the requests must be authorized.
Here is my code.
JWTAuthenticationFilter.java
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
#Autowired
CustomUserDetailsService userService;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
try {
CustomUserDetails user = new ObjectMapper().readValue(request.getInputStream(), CustomUserDetails.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>()));
} catch (Exception e) {
}
return super.attemptAuthentication(request, response);
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication auth) {
String loggedInUser = ((CustomUserDetails) auth.getPrincipal()).getUsername();
Claims claims = Jwts.claims().setSubject(loggedInUser);
if (loggedInUser != null) {
CustomUserDetails user = (CustomUserDetails) userService.loadUserByUsername(loggedInUser);
String roles[] = {};
for (Role role : user.getUser().getUserRoles()) {
roles[roles.length + 1] = role.getRole();
}
claims.put("roles", roles);
claims.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME));
}
String token = Jwts.builder().setClaims(claims)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET.getBytes()).compact();
response.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
}
}
JWTAuthorizationFilter.java
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
String header = request.getHeader(HEADER_STRING);
if (header == null || !header.startsWith(TOKEN_PREFIX)) {
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = getToken(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
#SuppressWarnings("unchecked")
private UsernamePasswordAuthenticationToken getToken(HttpServletRequest request) {
String token = request.getHeader(HEADER_STRING);
System.out.println("-----------------------------------------------------");
System.out.println("Token: " + token);
System.out.println("-----------------------------------------------------");
if (token != null) {
Claims claims = Jwts.parser().setSigningKey(SECRET.getBytes())
.parseClaimsJws(token.replace(TOKEN_PREFIX, "")).getBody();
String user = claims.getSubject();
ArrayList<String> roles = (ArrayList<String>) claims.get("roles");
ArrayList<MyGrantedAuthority> rolesList = new ArrayList<>();
if (roles != null) {
for (String role : roles) {
rolesList.add(new MyGrantedAuthority(role));
}
}
if (user != null) {
return new UsernamePasswordAuthenticationToken(user, null, null);
}
return null;
}
return null;
}
}
SecurityConfig.java
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Qualifier("userDetailsService")
#Autowired
CustomUserDetailsService userDetailsService;
#Autowired
PasswordEncoder passwordEncoder;
#Autowired
AuthenticationManager authenticationManager;
#Autowired
JWTAuthenticationEntryPoint jwtAuthenticationEntryPoint;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
try {
auth.userDetailsService(this.userDetailsService).passwordEncoder(passwordEncoder);
} catch (Exception e) {
}
}
/*
* #Autowired public void configureGlobal(AuthenticationManagerBuilder auth)
* throws Exception {
* auth.inMemoryAuthentication().withUser("student").password("student").roles(
* "student").and().withUser("admin") .password("admin").roles("admin"); }
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
// http.authorizeRequests().anyRequest().permitAll();
// http.authorizeRequests().antMatchers("/api/**").permitAll();
http.addFilter(new JWTAuthenticationFilter(authenticationManager));
http.addFilter(new JWTAuthorizationFilter(authenticationManager));
http.authorizeRequests().antMatchers("/api/student/**").hasAnyRole("STUDENT", "ADMIN");
http.authorizeRequests().antMatchers("/api/admin/**").hasRole("ADMIN");
http.authorizeRequests().antMatchers("/api/libararian/**").hasAnyRole("LIBRARIAN", "ADMIN");
http.authorizeRequests().antMatchers("/api/staff/**").hasAnyRole("STAFF", "ADMIN");
http.authorizeRequests().antMatchers("/api/teacher/**").hasAnyRole("TEACHER", "ADMIN");
http.authorizeRequests().antMatchers("/api/parent/**").hasAnyRole("PARENT", "ADMIN");
http.httpBasic().authenticationEntryPoint(jwtAuthenticationEntryPoint);
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// http.formLogin().and().logout().logoutSuccessUrl("/login?logout").permitAll();
}
}
MyGrantedAuthority.java
public class MyGrantedAuthority implements GrantedAuthority {
String authority;
MyGrantedAuthority(String authority) {
this.authority = authority;
}
#Override
public String getAuthority() {
// TODO Auto-generated method stub
return authority;
}
}
JWTAuthenticationEntryPoint.java
#Component
public class JWTAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
response.setStatus(403);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
String message;
if (exception.getCause() != null) {
message = exception.getCause().getMessage();
} else {
message = exception.getMessage();
}
byte[] body = new ObjectMapper().writeValueAsBytes(Collections.singletonMap("error", message));
response.getOutputStream().write(body);
}
}
I got it.
I followed another tutorial which made my job easy.
Here is the complete rewrite working code
TokenProvider.java
package com.cloudsofts.cloudschool.security;
import static com.cloudsofts.cloudschool.security.SecurityConstants.EXPIRATION_TIME;
import static com.cloudsofts.cloudschool.security.SecurityConstants.SECRET;
import java.util.ArrayList;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import com.cloudsofts.cloudschool.people.users.pojos.CustomUserDetails;
import com.cloudsofts.cloudschool.people.users.pojos.Role;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
#Component
public class TokenProvider {
#Autowired
CustomUserDetailsService userService;
public String createToken(String username) {
CustomUserDetails user = (CustomUserDetails) userService.loadUserByUsername(username);
Claims claims = Jwts.claims().setSubject(username);
ArrayList<String> rolesList = new ArrayList<String>();
for (Role role : user.getUser().getUserRoles()) {
rolesList.add(role.getRole());
}
claims.put("roles", rolesList);
String token = Jwts.builder().setClaims(claims)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)).setIssuedAt(new Date())
.signWith(SignatureAlgorithm.HS512, SECRET).compact();
return token;
}
public Authentication getAuthentication(String token) {
String username = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody().getSubject();
UserDetails userDetails = this.userService.loadUserByUsername(username);
return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
}
}
JWTFilter.java
package com.cloudsofts.cloudschool.security;
import static com.cloudsofts.cloudschool.security.SecurityConstants.HEADER_STRING;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.GenericFilterBean;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
public class JWTFilter extends GenericFilterBean {
public final static String AUTHORIZATION_HEADER = "Authorization";
private final TokenProvider tokenProvider;
public JWTFilter(TokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
try {
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
String jwt = resolveToken(httpRequest);
if (jwt != null) {
Authentication authentication = this.tokenProvider.getAuthentication(jwt);
if (authentication != null) {
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(servletRequest, servletResponse);
} catch (ExpiredJwtException | UnsupportedJwtException | MalformedJwtException | SignatureException
| UsernameNotFoundException e) {
// Application.logger.info("Security exception {}", e.getMessage());
((HttpServletResponse) servletResponse).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
}
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader(HEADER_STRING);
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7, bearerToken.length());
}
return null;
}
}
JWTConfigurer.java
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
public class JWTConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private final TokenProvider tokenProvider;
public JWTConfigurer(TokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
#Override
public void configure(HttpSecurity http) throws Exception {
JWTFilter customFilter = new JWTFilter(tokenProvider);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}
SecurityConfig.java
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.cloudsofts.cloudschool.people.users.pojos.User;
#RestController
public class LoginController {
private AuthenticationManager authenticationManager;
private TokenProvider tokenProvider;
private CustomUserDetailsService userService;
LoginController(AuthenticationManager auth, CustomUserDetailsService service, TokenProvider tokenProvider) {
this.authenticationManager = auth;
this.userService = service;
this.tokenProvider = tokenProvider;
}
#PostMapping("/login")
public String getToken(#RequestBody User user, HttpServletResponse response) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(user.getUsername(),
user.getPassword());
authenticationManager.authenticate(authToken);
return tokenProvider.createToken(user.getUsername());
}
}
LoginController.java
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.cloudsofts.cloudschool.people.users.pojos.User;
#RestController
public class LoginController {
private AuthenticationManager authenticationManager;
private TokenProvider tokenProvider;
private CustomUserDetailsService userService;
LoginController(AuthenticationManager auth, CustomUserDetailsService service, TokenProvider tokenProvider) {
this.authenticationManager = auth;
this.userService = service;
this.tokenProvider = tokenProvider;
}
#PostMapping("/login")
public String getToken(#RequestBody User user, HttpServletResponse response) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(user.getUsername(),
user.getPassword());
authenticationManager.authenticate(authToken);
return tokenProvider.createToken(user.getUsername());
}
}
Link to the Github project that helped me.
I am also using jwt authentication on my project and I could see that you are missing an entry point which should be used on the project. I will tell you how I implemented it and see if it can help you =).
You need to implement an authenticationEntryPoint in order to tell the code how the authentication will be done. It can be added after the filters, on the http.authorizerequest, with the command:
.authenticationEntryPoint(jwtAuthEndPoint);
where jwtAuthEndPoint is the following component:
#Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
AuthenticationException e) throws IOException, ServletException {
httpServletResponse.setStatus(SC_FORBIDDEN);
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
String message;
if (e.getCause() != null) {
message = e.getCause().getMessage();
} else {
message = e.getMessage();
}
byte[] body = new ObjectMapper().writeValueAsBytes(Collections.singletonMap("error", message));
httpServletResponse.getOutputStream().write(body);
}
}
I would also suggest you to take a look on this tutorial, which helped me A LOT in this case: https://sdqali.in/blog/2016/07/07/jwt-authentication-with-spring-web---part-4/
package com.batch.hibernate.config;
import javax.sql.DataSource;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.step.skip.SkipPolicy;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.LineMapper;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.batch.item.file.transform.LineTokenizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.FileSystemResource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import com.batch.hibernate.job.FileVerificationSkipper;
import com.batch.hibernate.job.UserItemPreparedStatementSetter;
import com.batch.hibernate.job.UserItemProcessor;
import com.batch.hibernate.model.User;
#Configuration
#EnableBatchProcessing
/*#ComponentScan(basePackages = { "com.batch.hibernate" })
#PropertySource("classpath:application.properties")*/
public class BatchConfiguration {
#Autowired
private Environment environment;
#Autowired
public JobBuilderFactory jobBuilderFactory;
#Autowired
public StepBuilderFactory stepBuilderFactory;
#Autowired
public DataSource dataSource;
#Bean
public DataSource dataSource(){
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getProperty("connection.driver_class"));
dataSource.setUrl(environment.getProperty("connection.url"));
dataSource.setUsername(environment.getProperty("connection.username"));
dataSource.setPassword(environment.getProperty("connection.password"));
return dataSource;
}
#Bean
public FlatFileItemReader<User> reader(){
FlatFileItemReader<User> reader = new FlatFileItemReader<User>();
reader.setResource(new FileSystemResource(environment.getProperty("local.filesystem.path")));
reader.setLinesToSkip(Integer.valueOf(environment.getProperty("header.lines.in.file")));
LineMapper<User> userLineMapper = createUserLineMapper();
reader.setLineMapper(userLineMapper);
return reader;
}
private LineMapper<User> createUserLineMapper() {
DefaultLineMapper<User> userLineMapper = new DefaultLineMapper<>();
LineTokenizer userLineTokenizer = createUserLineTokenizer();
userLineMapper.setLineTokenizer(userLineTokenizer);
FieldSetMapper<User> userInformationMapper = createUserInformationMapper();
userLineMapper.setFieldSetMapper(userInformationMapper);
return userLineMapper;
}
private LineTokenizer createUserLineTokenizer() {
DelimitedLineTokenizer userLineTokenizer = new DelimitedLineTokenizer();
userLineTokenizer.setDelimiter(environment.getProperty("column.delimiter"));
userLineTokenizer.setNames(environment.getProperty("column.names").split(","));
return userLineTokenizer;
}
private FieldSetMapper<User> createUserInformationMapper() {
BeanWrapperFieldSetMapper<User> userInformationMapper = new BeanWrapperFieldSetMapper<>();
userInformationMapper.setTargetType(User.class);
return userInformationMapper;
}
#Bean
public UserItemProcessor processor(){
return new UserItemProcessor();
}
#Bean
public JdbcBatchItemWriter<User> writer(){
JdbcBatchItemWriter<User> writer = new JdbcBatchItemWriter<User>();
writer.setDataSource(dataSource);
writer.setSql("INSERT INTO user (name, id) VALUES (?,?)");
writer.setItemPreparedStatementSetter(new UserItemPreparedStatementSetter());
return writer;
}
#Bean
public Step step1(){
return stepBuilderFactory.get("step1")
.<User, User> chunk(10000)
.reader(reader())
.faultTolerant()
.skipPolicy(fileVerificationSkipper())
.processor(processor())
.writer(writer())
.build();
}
#Bean
public Job importUserJob(){
return jobBuilderFactory.get("importUserJob")
.incrementer(new RunIdIncrementer())
.flow(step1())
.end()
.build();
}
#Bean
public SkipPolicy fileVerificationSkipper() {
return new FileVerificationSkipper();
}
/*#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}*/
}
and my HibernateUtil.java is:
package com.batch.hibernate.util;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import com.batch.hibernate.model.User;
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SpringBatchUtil springBatchUtil;
private static Properties properties;
public static SessionFactory buildSessionFactory() {
SessionFactory localSessionFactory = null;
springBatchUtil = new SpringBatchUtil();
try {
Configuration configuration = new Configuration();
properties = springBatchUtil.loadProperties();
configuration.setProperty(SpringBatchConstants.HIBERNATE_CONNECTION_URL,
properties.getProperty(SpringBatchConstants.HIBERNATE_CONNECTION_URL));
configuration.setProperty(SpringBatchConstants.HIBERNATE_CONNECTION_USERNAME,
properties.getProperty(SpringBatchConstants.HIBERNATE_CONNECTION_USERNAME));
configuration.setProperty(SpringBatchConstants.HIBERNATE_CONNECTION_PASSWORD,
properties.getProperty(SpringBatchConstants.HIBERNATE_CONNECTION_PASSWORD));
configuration.setProperty(SpringBatchConstants.HIBERNATE_SHOW_SQL,
properties.getProperty(SpringBatchConstants.HIBERNATE_SHOW_SQL));
configuration.setProperty(SpringBatchConstants.HIBERNATE_CURRENT_SESSION_CONTEXT_CLASS,
properties.getProperty(SpringBatchConstants.HIBERNATE_CURRENT_SESSION_CONTEXT_CLASS));
configuration.setProperty(SpringBatchConstants.HIBERNATE_CONNECTION_DRIVER_CLASS,
properties.getProperty(SpringBatchConstants.HIBERNATE_CONNECTION_DRIVER_CLASS));
configuration.addPackage("com.batch.hibernate.model");
configuration.addAnnotatedClass(User.class);
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
localSessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (HibernateException he) {
he.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return localSessionFactory;
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Session getSession() throws Exception {
if (getSessionFactory() == null) {
throw new HibernateException("Initial SessionFactory creation failed.");
}
Session session = getSessionFactory().getCurrentSession();
session.getTransaction().begin();
return session;
}
public static void closeSession(Session session) {
if (session != null) {
if (session.getTransaction().isActive()) {
session.getTransaction().commit();
}
session.close();
}
}
}
I have dataSource settings and hibernateUtil as above, I want to use hibernate rather than JDBC while configuring dataSource.
The prime reason to integrate with hibernate is for auditing purpose while writing records from file to database.
How can I use hibernate here in this context? or Is there a way to audit using the way I am already using?
Sorry if i am not clear with my question.
Have a look at Spring-starter-data-jpa. Set the needed properties like hibernate.dialect etc, and you don't need to do anything yourself, it works o.o.t.b.
Spring data jpa should be enough to solve all your issues.
Please look at this Repo for starter guide .
https://github.com/rahulrsingh09/Spring-Boot-DataJPA
I'm having bad time dealing with a simple application that must monitor a folder for new files, take each file and consume RESTful service ( one of my other apps) and send the response files using spring integration FTP Outbound channel adapter
It has following structure:
Initializer:
package com.ftpoutbound;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import com.ftpoutbound.client.FtpoutboundApp;
public class ServletInitializer extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(FtpoutboundApp.class);
}
}
I define beans in FtpoutboundApp:
package com.ftpoutbound.client;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.context.ApplicationContext;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.file.FileNameGenerator;
import org.springframework.integration.file.remote.session.CachingSessionFactory;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.ftp.outbound.FtpMessageHandler;
import org.springframework.integration.ftp.session.DefaultFtpSessionFactory;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate;
import com.ftpoutbound.monitor.MonitorDirectory;
#Configuration
#SpringBootApplication
#ComponentScan({ "com.ftpoutbound" })
#IntegrationComponentScan
#EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
#EnableScheduling
public class FtpoutboundApp implements ApplicationContextAware {
final static Logger logger = Logger.getLogger(FtpoutboundApp.class);
#Autowired
private MonitorDirectory monitor;
#Autowired
MyGateway gateway;
#Value("${remotedirectory}")
private String remotedirectory;
#Value("${remotehost}")
private String remotehost;
#Value("${remoteport}")
private int remoteport;
#Value("${remoteuser}")
private String remoteuser;
#Value("${remotepassword}")
private String remotepassword;
#Value("${outbound214sname}")
private String outbound214sname;
public static void main(String[] args) {
SpringApplication.run(FtpoutboundApp.class, args);
}
public void createGateway(File file214) {
try {
gateway.sendToFtp(file214);
file214.delete();
} catch (Exception e) {
logger.error("ERROR APP OUTBOUND\n");
logger.error(e);
}
}
#Bean
public SessionFactory<FTPFile> ftpSessionFactory() {
DefaultFtpSessionFactory sf = new DefaultFtpSessionFactory();
sf.setHost(remotehost);
sf.setPort(remoteport);
sf.setUsername(remoteuser);
sf.setPassword(remotepassword);
return new CachingSessionFactory<FTPFile>(sf);
}
#Bean
#ServiceActivator(inputChannel = "ftpChannel")
public MessageHandler handler() {
FtpMessageHandler handler = new FtpMessageHandler(ftpSessionFactory());
handler.setRemoteDirectoryExpression(new LiteralExpression(remotedirectory));
handler.setFileNameGenerator(new FileNameGenerator() {
#Override
public String generateFileName(Message<?> message) {
String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
String time = new SimpleDateFormat("HHmmssssssss").format(new Date());
return outbound214sname + "." + date + time;
}
});
return handler;
}
#MessagingGateway
public interface MyGateway {
#Gateway(requestChannel = "ftpChannel")
void sendToFtp(File file);
}
#EventListener
public void afterApplicationReady(ApplicationReadyEvent event) {
try {
logger.info("INICIO DE MONITOREO DE ARCHIVOS HG");
monitor.startMonitoring();
} catch (IOException e) {
logger.error("ERROR EN MONITOREO DE FOLDER ENTRADA ARCHIVOS HG:\n" + e);
} catch (InterruptedException e) {
logger.error("INTERRUPCIĆN EN MONITOREO DE FOLDER ENTRADA ARCHIVOS HG:\n" + e);
}
}
#Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
}
}
The monitor started from the FtpoutboundApp:
I'm using SCHEDULED annotation since Watchservice was not working either
package com.ftpoutbound.monitor;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.ClosedWatchServiceException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.ftpoutbound.client.FtpoutboundApp;
import com.ftpoutbound.restfulclient.httpPost;
#Component
public class MonitorDirectory {
final static Logger logger = Logger.getLogger(MonitorDirectory.class);
#Autowired
private httpPost httppost;
#Value("${inboundhgfilesfolder}")
private String inboundhgfilesfolder;
#Value("${inboundhgfilesfolderbak}")
private String inboundhgfilesfolderbak;
#Value("${hglin}")
private String hglin;
#Scheduled(fixedRate = 10000)
public void startMonitoring() throws IOException, InterruptedException {
try {
listFiles();
} catch (Exception e) {
logger.error("ERROR MONITOREANDO FOLDER");
logger.error(e);
}
}
public void listFiles() throws Exception {
File directory = new File(inboundhgfilesfolder);
File[] fList = directory.listFiles();
for (File file : fList) {
String fileName = file.getName();
if (file.isFile()) {
readFile(fileName);
Thread.sleep(1000);
}
}
}
public void readFile(String fileName) throws IOException {
String hgFile = fileName.substring(0, 7);
if (hgFile.equals(hglin)) {
InputStream input = new FileInputStream(inboundhgfilesfolder + fileName);
StringBuilder builder = new StringBuilder();
int ch;
while ((ch = input.read()) != -1) {
builder.append((char) ch);
}
try {
httppost.get214fromRestful(builder.toString());
} catch (Exception e) {
logger.error("ERROR EN POST REQUEST DESDE APP OUTBOUND:\n" + e);
}
}
moveFile(fileName);
}
public void moveFile(String fileName) {
Path source = Paths.get(inboundhgfilesfolder + fileName);
Path newdir = Paths.get(inboundhgfilesfolderbak + fileName);
try {
Files.move(source, newdir);
} catch (IOException e) {
logger.error("ERROR MOVIENDO ARCHIVO:\n" + e);
}
}
}
And the HTTPclient that consumes the RESTful app
package com.ftpoutbound.restfulclient;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import com.ftpoutbound.client.FtpoutboundApp;
#Component
public class httpPost {
final static Logger logger = Logger.getLogger(httpPost.class);
#Value("${restful214url}")
private String restful214url;
#Value("${outbound214sfolder}")
private String outbound214sfolder;
#Autowired
private FtpoutboundApp ftpoutbound;
public void get214fromRestful(String hgfile) throws Exception {
logger.info("OBTENIENDO 214");
logger.info("DIRECCION" + restful214url);
logger.info("ARCHIVO" + hgfile);
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.postForObject(restful214url, hgfile, String.class);
File file = createFile214local(result.toString());
logger.info("RESULTADO DE POST:");
logger.info(result.toString());
ftpoutbound.createGateway(file);
}
private File createFile214local(String hgfile) {
logger.info("ESCRIBIENDO 214");
File file = new File(outbound214sfolder + "214.tmp");
try {
file.createNewFile();
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(hgfile);
bw.close();
} catch (IOException e) {
logger.error("ERROR ESCRIBIENDO FILE:\n->" + e);
}
return file;
}
}
but the app seems not working, it freezes before consuming the RESTful in:
logger.info("OBTENIENDO 214");
logger.info("DIRECCION" + restful214url);
logger.info("ARCHIVO" + hgfile);
I noticed these lines are printed twice in the log, still not sure if this is a threads issue or what causes the APP to not even finish the deployment in the server, I have another similar App (except that one doesn't consume RESTful) and it works OK, another FTPInbound channel Adapter and it works OK, but I have some days figuring what I'm missing or What's the best way to do this.
Believe me, Help will be extremely appreciated.
The issue was that
my outbound channel configuration class was implementing ApplicationContextAware and it was causing the RestTemplate to freezes the App when consuming my Microservices App, so I changed to extend SpringBootServletInitializer and implement WebApplicationInitializerand it worked.
I tried to much things and it doesn't worked. I want the data inserted on my DB to rollback when an error occurs on vacationsDao.requestVacations. Here's my code:
VacationsService:
import java.text.ParseException;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.autozone.web.dao.VacationsDao;
import com.autozone.web.exception.InvalidVacationsException;
#Service
public class VacationsServiceImpl implements VacationsService {
private ValidationService validationService;
private VacationsDao vacationsDao;
#Autowired
public VacationsServiceImpl(ValidationService validationService,
VacationsDao vacationsDao) {
this.validationService = validationService;
this.vacationsDao = vacationsDao;
}
#Override
#Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void requestVacations(String username, Set<String> days)
throws InvalidVacationsException {
if (validationService.validateUsername(username)) {
for (String day : days) {
try {
if (!validationService.validateDate(day)) {
throw new InvalidVacationsException(
"Wrong date format. Must use 'yyyy-MM-dd'.");
}
} catch (ParseException e) {
e.printStackTrace();
throw new InvalidVacationsException(
"Wrong date format. Must use 'yyyy-MM-dd'.");
}
}
try {
vacationsDao.requestVacations(username, days);
} catch (DuplicateKeyException e) {
throw new InvalidVacationsException(
"Dates already requested from this user.");
}
} else {
throw new InvalidVacationsException(
"Wrong username format. Must only contains alphanumeric and starts with letters.");
}
}
}
VacationsDao
import java.util.Set;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
#Repository
public class VacationsDaoImpl implements VacationsDao {
JdbcTemplate jdbcTemplate;
#Autowired
public void setDataSource(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
// It inserts all data when an exception occurs. Check later.
#Override
public void requestVacations(String username, Set<String> days)
throws DuplicateKeyException {
StringBuilder insert = new StringBuilder(
"INSERT INTO cc_vacations(username, day) VALUES ");
String prefix = "";
for (String day : days) {
insert.append(prefix);
insert.append("('");
insert.append(username);
insert.append("', '");
insert.append(day);
insert.append("')");
prefix = ",";
}
jdbcTemplate.update(insert.toString());
}
}
DbConfig
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableTransactionManagement
public class DbConfig {
#Bean
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://callcenter.autozone.com/callcenter");
dataSource.setUsername("callcenter");
dataSource.setPassword("h3lp1n5");
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(getDataSource());
}
}
Thanks for your help! :)