Spring boot with spring batch and jpa -configuration - spring

I have simple batch application, reading csv to postgres database.
I have uploaded the code in this below repo in bitbucket
https://github.com/soasathish/spring-batch-with-jpa.git
I have problems in configuring the writing to database using spring data JPA.
I am getting manage bean not found .issue.
This same jpa spring data configuration works in different project when i tried to integrate with spring batch it fails with manage bean not found.
The batch config has spring job
There is only one step
1) reader -read from csv files.
processor applies some rules on the files .. Drools
please run schema-postgresql.sql to setup database
WRITER USES THE SPRING DATA JPA TO WRITE TO DB
could one help
I have uploaded the code in this below repo in bitbucket
https://github.com/soasathish/spring-batch-with-jpa.git
i know its a minor issue , but any direction or help will be grateful
code for creating repo
=======================
package uk.gov.iebr.batch.config;
import static uk.gov.iebr.batch.config.AppProperties.DRIVER_CLASS_NAME;
import static uk.gov.iebr.batch.config.AppProperties.IEBR_DB_PASSWORD_KEY;
import static uk.gov.iebr.batch.config.AppProperties.IEBR_DB_URL_KEY;
import static uk.gov.iebr.batch.config.AppProperties.IEBR_DB_USER_KEY;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
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;
#Configuration
#PropertySource({"classpath:application.properties"})
#EnableJpaRepositories({"uk.gov.iebr.batch.repository"})
#EnableTransactionManagement
#ComponentScan(basePackages="uk.gov.iebr.batch.repository")
public class DataSourceConfiguration {
#Autowired
Environment env;
#Bean(name = "allsparkEntityMF")
public LocalContainerEntityManagerFactoryBean allsparkEntityMF() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(allsparkDS());
em.setPersistenceUnitName("allsparkEntityMF");
em.setPackagesToScan(new String[] { "uk.gov.iebr.batch"});
em.setPackagesToScan(new String[] { "uk.gov.iebr.batch.repository"});
em.setPersistenceProvider(new HibernatePersistenceProvider());
HibernateJpaVendorAdapter a = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(a);
Properties p = hibernateSpecificProperties();
p.setProperty("hibernate.ejb.entitymanager_factory_name", "allsparkEntityMF");
em.setJpaProperties(p);
return em;
}
#Bean(name = "allsparkDS")
public DataSource allsparkDS() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty(DRIVER_CLASS_NAME));
dataSource.setUrl(env.getProperty(IEBR_DB_URL_KEY));
dataSource.setUsername(env.getProperty(IEBR_DB_USER_KEY));
dataSource.setPassword(env.getProperty(IEBR_DB_PASSWORD_KEY));
return dataSource;
}
#Bean
public Properties hibernateSpecificProperties(){
final Properties p = new Properties();
p.setProperty("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.hibernate.ddl-auto"));
p.setProperty("hibernate.dialect", env.getProperty("spring.jpa.hibernate.dialect"));
p.setProperty("hibernate.show-sql", env.getProperty("spring.jpa.show-sql"));
p.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("spring.jpa.hibernate.cache.use_second_level_cache"));
p.setProperty("hibernate.cache.use_query_cache", env.getProperty("spring.jpa.hibernate.cache.use_query_cache"));
return p;
}
#Bean(name = "defaultTm")
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(allsparkEntityMF().getObject());
return txManager;
}
}
Batch config file:
package uk.gov.iebr.batch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import uk.gov.iebr.batch.config.AllSparkDataSourceConfiguration;
import uk.gov.iebr.batch.config.DataSourceConfiguration;
import uk.gov.iebr.batch.dao.PersonDao;
import uk.gov.iebr.batch.model.Person;
import uk.gov.iebr.batch.step.Listener;
import uk.gov.iebr.batch.step.Processor;
import uk.gov.iebr.batch.step.Reader;
import uk.gov.iebr.batch.step.Writer;
#Configuration
#EnableBatchProcessing
//spring boot configuration
#EnableAutoConfiguration
//file that contains the properties
#PropertySource("classpath:application.properties")
#Import({DataSourceConfiguration.class, AllSparkDataSourceConfiguration.class})
public class BatchConfig {
private static final Logger log = LoggerFactory.getLogger(BatchConfig.class);
#Autowired
public JobBuilderFactory jobBuilderFactory;
#Autowired
public StepBuilderFactory stepBuilderFactory;
#Autowired
public PersonDao PersonDao;
#Autowired
public DataSourceConfiguration dataSourceConfiguration;
#Bean
public Job job() {
long startTime = System.currentTimeMillis();
log.info("START OF BATCH ========================================================================" +startTime);
return jobBuilderFactory.get("job").incrementer(new RunIdIncrementer())
//.listener(new Listener(PersonDao))
.flow(step1()).end().build();
}
#Bean
public Step step1() {
return stepBuilderFactory.get("step1").<Person, Person>chunk(10)
.reader(Reader.reader("tram-data.csv"))
.processor(new Processor()).writer(new Writer(PersonDao)).build();
}
}
Writer calls this PersonDaoImpl:
public class PersonDaoImpl implements PersonDao {
#Autowired
DataSourceConfiguration dataSource;
#Autowired
PersonRepository personrepo;
#Override
public void insert(List<? extends Person> Persons) {
personrepo.save(Persons);
}
}

Based on the code you provided and the stack trace in your comment.
It's complaining that it can't find a #Bean named entityManagerFactory.
The reason this is happening is because you are using #EnableJpaRepositories and the entityManagerFactoryRef property defaults to entityManagerFactory. This property defines the name of the #Bean for the EntityManagerFactory.
I think your application configuration is preventing the normal auto-configuration from spring-boot from being processed.
I would recommend removing the IEBRFileProcessApplication class and following this example for configuring your spring-boot application (you could use ServletInitializer if you want).
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
I also can't really see a need for DataSourceConfiguration and AllSparkDataSourceConfiguration, so I would recommend removing them. If you really need to specify your own DataSource, let me know and I can provide an additional example.
Between the #SpringBootApplication and #EnableBatchProcessing annotations, everything that is necessary will be bootstrapped for you.
All you need on BatchConfig is #Configuration and #EnableBatchProcessing.
If you make these changes to simplify your code base, then your problems should disappear.
UPDATE:
I created a pull request located here https://github.com/soasathish/spring-batch-with-jpa/pull/1
Please take a look at the javadoc here for an explanation on how #EnableBatchProcessing works. http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.html

Related

Spring ignores Beans, Qualifier and Transactional

Hi trying to set simple rest controller with several databases. Problem is Spring ignores both Transactional from my service, it always go to #Primary. Also Spring ignores the Qualifier inside DataSourceTransactionaManager and seems to go to default #Primary. Anyone help much appreciated.
edit: added import statements.. hikari imports i due too i changed the code little bit and instead use hikari database and also tried entitymanager..but neither of those things helped..
package com.example.miniredditbackend.user;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service
public class UserService implements UserSer{
private UserRepo userRep;
#Autowired
public UserService(UserRepo userRep){
this.userRep = userRep;
}
#Override
#Transactional("tm1")
public User createUser(User user){
return userRep.save(user);
}
}
package com.example.miniredditbackend.user;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "entityuser",
transactionManagerRef = "tm2",
basePackages = {
"com.example.miniredditbackend.user"
}
)
public class userDatabase {
#Bean(name = "userdb")
#ConfigurationProperties(prefix = "userdatabase.datasource")
public DataSource userdb(){
return DataSourceBuilder.create().build();
}
#Bean(name = "entityuser")
public LocalContainerEntityManagerFactoryBean entityU(EntityManagerFactoryBuilder builder,
#Qualifier ("userdb") DataSource datasource){
return builder.dataSource(datasource).packages("com.example.miniredditbackend.user").persistenceUnit("usersx").build();
}
#Bean(name = "tm2")
public PlatformTransactionManager tm2(#Qualifier ("entityuser") EntityManagerFactory entityuser){
return new JpaTransactionManager(entityuser);
}
}

Difference between Spring Boot QuartzAutoConfiguration 2.1.6.RELEASE & 2.2.2.RELEASE

We were using Spring Boot 2.1.6.RELEASE.
after that we updated spring version to 2.2.2.RELEASE. When we change the version we noticed our quartz jobs not working. We have multiple jobs and we configured them like below. After some reasearch i found some differences between in QuartzAutoConfiguration class.
How can i inject my triggers in spring 2.2.2.RELEASE. Is there any easy way? I dont want to write to many triggers and trigger details.
MyConfig
import io.rkpc.commons.util.ApplicationReflectionUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
#Slf4j
#Configuration
#ConfigurationProperties(prefix = "quartz")
#Profile("quartz")
#Data
public class JobConfig {
private List<Job> jobs;
#Bean
public JobDetail[] jobDetail() throws SchedulerConfigException {
Set<Class<QuartzJobBean>> subClasses = ApplicationReflectionUtil.getSubClasses(QuartzJobBean.class, "io.rkpc");
List<JobDetail> jobDetails = new ArrayList<>();
for (Class<QuartzJobBean> quartzJobBeanClass : subClasses) {
Job job = getJob(quartzJobBeanClass.getSimpleName());
if (job.isEnabled()) {
JobDetail jobDetail = JobBuilder.newJob(quartzJobBeanClass)
.withIdentity(quartzJobBeanClass.getSimpleName())
.storeDurably()
.build();
jobDetails.add(jobDetail);
}
}
return jobDetails.toArray(new JobDetail[0]);
}
#Bean
public Trigger[] jobATrigger(JobDetail[] jobADetails) throws SchedulerConfigException {
List<Trigger> triggers = new ArrayList<>();
for (JobDetail jobDetail : jobADetails) {
Job job = getJob(jobDetail.getKey().getName());
CronTrigger trigger = TriggerBuilder.newTrigger().forJob(jobDetail)
.withIdentity(jobDetail.getKey().getName().concat("Trigger"))
.withSchedule(CronScheduleBuilder.cronSchedule(job.getCron()))
.build();
triggers.add(trigger);
}
return triggers.toArray(new Trigger[0]);
}
private Job getJob(String name) throws SchedulerConfigException {
List<Job> filteredJobs = jobs.stream().filter(job -> job.getName().equals(name)).collect(Collectors.toList());
if (CollectionUtils.isEmpty(filteredJobs) || filteredJobs.size() > 1) {
log.error("{} is not configured", name);
throw new SchedulerConfigException("Job is not configured");
}
return filteredJobs.get(0);
}
#Data
public static class Job {
private String name;
private String cron;
private boolean enabled;
}
}
QuartzAutoConfiguration.java Spring version 2.1.6 github url ; https://github.com/spring-projects/spring-boot/blob/v2.1.6.RELEASE/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java
QuartzAutoConfiguration.java Spring version 2.2.2 github url https://github.com/spring-projects/spring-boot/blob/v2.2.2.RELEASE/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java
Main difference i notice is ; in 2.1.6 version Quartz AutoConfiguration was "Trigger" array but 2.2.2 doesn't have "Trigger" array.
Spring has always some magic :)
import io.rkpc.commons.util.ApplicationReflectionUtil;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import javax.validation.constraints.NotNull;
import java.text.ParseException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
#Slf4j
#Configuration
#ConfigurationProperties(prefix = "quartz")
#Profile("quartz")
#Data
#AutoConfigureBefore({QuartzAutoConfiguration.class})
#RequiredArgsConstructor(onConstructor = #__({#Autowired, #NotNull}))
public class JobConfig {
private final List<Job> jobs;
private final DefaultListableBeanFactory beanFactory;
#PostConstruct
public void init() throws SchedulerConfigException, ParseException {
Set<Class<QuartzJobBean>> subClasses = ApplicationReflectionUtil.getSubClasses(QuartzJobBean.class, "io.rkpc");
for (Class<QuartzJobBean> quartzJobBeanClass : subClasses) {
Job job = getJob(quartzJobBeanClass.getSimpleName(), jobs);
if (job.isEnabled()) {
JobDetailImpl jobDetail = (JobDetailImpl) JobBuilder.newJob(quartzJobBeanClass)
.withIdentity(quartzJobBeanClass.getSimpleName())
.storeDurably()
.build();
CronTriggerImpl trigger = (CronTriggerImpl) TriggerBuilder.newTrigger().forJob(jobDetail)
.withIdentity(jobDetail.getKey().getName().concat("Trigger"))
.withSchedule(CronScheduleBuilder.cronSchedule(job.getCron()))
.build();
GenericBeanDefinition jobBeanDefinition = new GenericBeanDefinition();
jobBeanDefinition.setBeanClass(JobDetailImpl.class);
jobBeanDefinition.getPropertyValues().addPropertyValue("jobClass", quartzJobBeanClass);
jobBeanDefinition.getPropertyValues().addPropertyValue("key", jobDetail.getKey());
jobBeanDefinition.getPropertyValues().addPropertyValue("durability", jobDetail.isDurable());
beanFactory.registerBeanDefinition(quartzJobBeanClass.getSimpleName(), jobBeanDefinition);
GenericBeanDefinition triggerBeanDefinition = new GenericBeanDefinition();
triggerBeanDefinition.setBeanClass(CronTriggerImpl.class);
triggerBeanDefinition.getPropertyValues().addPropertyValue("jobKey", trigger.getJobKey());
triggerBeanDefinition.getPropertyValues().addPropertyValue("key", trigger.getKey());
triggerBeanDefinition.getPropertyValues().addPropertyValue("cronExpression", new CronExpression(trigger.getCronExpression()));
beanFactory.registerBeanDefinition(trigger.getName(), triggerBeanDefinition);
}
}
}
public Job getJob(String name, List<Job> jobs) throws SchedulerConfigException {
List<Job> filteredJobs = jobs.stream().filter(job -> job.getName().equals(name)).collect(Collectors.toList());
if (CollectionUtils.isEmpty(filteredJobs) || filteredJobs.size() > 1) {
log.error("{} is not configured", name);
throw new SchedulerConfigException("Job is not configured");
}
return filteredJobs.get(0);
}
#Data
public static class Job {
private String name;
private String cron;
private boolean enabled;
}
}
You are exposing a single Trigger[] bean rather than multiple Trigger beans. You should define one bean per Trigger. You should also do the same for each JobDetail. This was working by accident with Spring Boot 2.1.x as you were relying on the auto-configuration using ObjectProvider<Trigger[]>. The intent of the auto-configuration was to consume all Trigger beans, with the application context turning those beans into an array before injecting them.
If you don't want to define multiple Trigger and JobDetail beans, you may be better configuring the SchedulerFactoryBean yourself rather than relying on the auto-configuration.

property file not loading spring boot

My property file is location in src/main/resources in eclipse checked its in the classpath - however the following class is unable to initialize the env variable. Any help?
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.solr.core.SolrTemplate;
#Configuration
#PropertySource(value = { "classpath:solr.properties" })
public class SolrConfig {
#Autowired
private Environment env;
private final static Logger logger = LoggerFactory.getLogger(SolrConfig.class);
#Bean
public SolrClient solrClient() {
if(env == null )
{
logger.error("Property file not loaded!!!");
System.exit(1);
}
String servername = env.getProperty("solr.server");
return new HttpSolrClient.Builder(servername)
.build();
}
#Bean
public SolrTemplate solrTemplate(SolrClient client) throws Exception {
return new SolrTemplate(client);
}
}
You class annotation is correct, but try the following within your method:
Properties _properties = new Properties();
_properties.load(getClass().getClassLoader().getResourceAsStream("solr.properties"));
String servername = _properties.getProperty("solr.server");
I believe you're missing a PropertySourcesPlaceholderConfigurer registered.
From Spring documentation of #PropertySource:
In order to resolve ${...} placeholders in definitions or
#Value annotations using properties from a PropertySource, one must
register a PropertySourcesPlaceholderConfigurer. This happens
automatically when using in XML, but
must be explicitly registered using a static #Bean method when using
#Configuration classes.
So consider registering this bean:
#Bean
public static PropertySourcesPlaceholderConfigurer
propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}

Change #PersistenceContext to #PersistenceUnit while running Junit tests

I am using #PersistenceContext as of now and working fine. However the same application need to be used in Junit context as well. I want #PersistenceContext to be changed to #PersistenceUnit in DaoImpl classes when Junit test cases are running. How to do that?
Using the following versions in my application
<springframework.version>4.2.5.RELEASE</springframework.version>
<hibernate.version>5.1.0.Final</hibernate.version>
<hibernate.validator.version>5.2.4.Final</hibernate.validator.version>
<mysql.connector.version>6.0.3</mysql.connector.version>
<junit.version>4.12</junit.version>
Hibernate Configuration is:
package com.rsa.springwebclasses.configuration.db;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
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 ch.qos.logback.classic.Logger;
#Configuration
#EnableTransactionManagement
#PropertySources({
#PropertySource("classpath:hibernate/hibernate.properties"),
#PropertySource("classpath:mysql/mysql.properties")
})
public class HibernateConfiguration {
Logger logger = (Logger) LoggerFactory.getLogger(HibernateConfiguration.class);
#Autowired
Environment env;
private Properties getHibernateProperties() {
Properties hprop = new Properties();
hprop.put("hibernate.dialect", env.getRequiredProperty("mysql.hibernate.dialect"));
hprop.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
hprop.put("hibernate.format_sql", env.getRequiredProperty("hibernate.format_sql"));
logger.info("Hibernate properties: " + hprop.toString());
return hprop;
}
private Properties getMysqlProperties() {
Properties mySqlProp = new Properties();
mySqlProp.put("jdbc.driverClassName", env.getRequiredProperty("mysql.jdbc.driverClassName"));
mySqlProp.put("jdbc.url", env.getRequiredProperty("test.mysql.jdbc.url"));
mySqlProp.put("jdbc.username", env.getRequiredProperty("test.mysql.jdbc.username"));
mySqlProp.put("jdbc.password", env.getRequiredProperty("test.mysql.jdbc.password"));
logger.info("MySQL properties: " + mySqlProp.toString());
return mySqlProp;
}
#Bean
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
Properties dbProp = this.getMysqlProperties();
dataSource.setDriverClassName(dbProp.getProperty("jdbc.driverClassName"));
dataSource.setUrl(dbProp.getProperty("jdbc.url"));
dataSource.setUsername(dbProp.getProperty("jdbc.username"));
dataSource.setPassword(dbProp.getProperty("jdbc.password"));
logger.info("DataSource object is created.");
return dataSource;
}
#Bean
public PlatformTransactionManager getTransactionManager(EntityManagerFactory emf) {
JpaTransactionManager jtm = new JpaTransactionManager();
jtm.setEntityManagerFactory(emf);
logger.info("PlatformTransactionManager is initialized with JpaTransactionManager");
return jtm;
}
#Bean
public LocalContainerEntityManagerFactoryBean getEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
emfb.setDataSource(getDataSource());
emfb.setPackagesToScan(new String[] {"com.rsa.springwebclasses.model"});
JpaVendorAdapter vendor = new HibernateJpaVendorAdapter();
emfb.setJpaVendorAdapter(vendor);
emfb.setJpaProperties(getHibernateProperties());
logger.info("LocalContainerEntityManagerFactoryBean created: PersistentUnit Name: " + emfb.getJpaVendorAdapter().toString());
return emfb;
}
}
My DaoImpl class is:
package com.rsa.springwebclasses.dao.impl;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import com.rsa.springwebclasses.dao.UserDao;
import com.rsa.springwebclasses.model.User;
import ch.qos.logback.classic.Logger;
#Repository("userDao")
public class UserDaoImpl implements UserDao {
Logger logger = (Logger) LoggerFactory.getLogger(UserDaoImpl.class);
**#PersistenceContext**
EntityManager em;
public List<User> findAllUsers() {
logger.debug("In findAllUsers method.");
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> criteria = cb.createQuery(User.class);
Root<User> user = criteria.from(User.class);
criteria.select(user).orderBy(cb.asc(user.get("username")));
logger.debug("Exit findAllUsers method");
return em.createQuery(criteria).getResultList();
}
}
While injecting EntityManager, #PersistenceContext is hard coded. However the same DaoImpl class need to be used for Junit test cases as well. With Junit I prefer to use transaction type as RESOUCE_LOCAL which is possible only with #PersistenceUnit. Is it possible to have a different annotation in DaoImpl class and assign #PersistenceContext or #PersistenceUnit while application is loading or already running?

Spring security 3.2.5 and token based authentication

I'm trying to secure a REST API using Spring security 3.2.5 and a java based configuration.
Actually i've found many examples developed with an "old" xml approach, but nothing with a complete java configuration.
Where can i find some useful tutorial?
The project creates a REST API and some jsp usesd to allow the admin to populate an underlyin DB (Hibernate is used as ORM):
Here is my Config class:
package com.idk.fantappapaback.spring;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.tomcat.dbcp.dbcp.BasicDataSource; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; import org.springframework.orm.hibernate4.HibernateTransactionManager; import org.springframework.orm.hibernate4.LocalSessionFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.multipart.support.StandardServletMultipartResolver; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.JstlView; import org.springframework.web.servlet.view.UrlBasedViewResolver;
import com.google.common.base.Preconditions; import com.idk.fantappapaback.spring.security.SecurityConfig;
#Configuration #EnableWebMvc #EnableTransactionManagement #PropertySource({ "classpath:persistence-mysql.properties" }) #ComponentScan({ "com.idk.fantappapaback.persistence","com.idk.fantappapaback.rest","com.idk.fantappapaback.spring.controllers","com.idk.fantappapaback.spring.security" }) #Import({ SecurityConfig.class }) public class BackEndConfig extends WebMvcConfigurerAdapter{
#Autowired
private Environment env;
public BackEndConfig() {
super();
}
//l'application context estrae il session factory da questo bean
#Bean
public LocalSessionFactoryBean sessionFactory() {
final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan(new String[] { "com.idk.fantappapaback.persistence.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource restDataSource() {
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
return dataSource;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(final SessionFactory sessionFactory) {
final HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
final Properties hibernateProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
//***Proprieta per l'output delle query in sql che qui disabilito
// hibernateProperties.setProperty("hibernate.show_sql", "true");
// hibernateProperties.setProperty("hibernate.format_sql", "true");
// hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true");
return hibernateProperties;
}
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public StandardServletMultipartResolver multipartResolver(){
return new StandardServletMultipartResolver();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/"); // registry.addResourceHandler("/css/**") // .addResourceLocations("/css/"); // registry.addResourceHandler("/img/**") // .addResourceLocations("/img/");
registry.addResourceHandler("/js/**")
.addResourceLocations("/js/");
}
}
this is my very basic Security config that i use to have a form log in on the jsp views:
package com.idk.fantappapaback.spring.security;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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({ SecurityConfig.class }) nella BackEndConfig #Configuration #EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter{ #Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("masquenada").password("123456").roles("USER"); // auth.inMemoryAuthentication().withUser("masquenada").password("123456").roles("ADMIN"); auth.inMemoryAuthentication().withUser("masquenada").password("123456").roles("SUPERADMIN"); }
#Override protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() // .antMatchers("/players/**").access("hasRole('ROLE_USER')") .antMatchers("/createSeason/**").access("hasRole('ROLE_SUPERADMIN')") .and().formLogin().permitAll() .and().httpBasic();
} }
here is my SecurityWebApplicationInitializer :
package com.idk.fantappapaback.spring.security;
import org.springframework.security.web.context.*;
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}
The main question is : how to add the token based autorization?
I've added Spring oAuth 2 and Spring integration to my pom but i need some hint about introducing spring oAuth keeping the form login.
You need to "configure" your SecurityWebApplicatioInitializer.
http://spring.io/blog/2013/07/03/spring-security-java-config-preview-web-security/

Resources