BootstrapCacheLoader not working with spring boot - spring

I am using Spring Boot with EhCache and Jersey, I am having issue to make BootstrapCacheLoader work, debug shows the load function executes and make call to the function (for which I want result to be cached). but once app is started the first request still calls the function and takes it's time to load data and then afterwords it is quick i.e. first call takes around 2 minutes and then following requests take less than a second.
here is my implementation:
ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir" />
<cache name="idsMap"
maxEntriesLocalHeap="1000"
maxEntriesLocalDisk="10000"
eternal="true"
diskSpoolBufferSizeMB="20"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache>
</ehcache>
EhCache Config
package com.spinners.rest.config;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheFactoryBean;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
/**
* #author sajid
*
*/
#Configuration
#EnableCaching
public class EhCacheConfig {
#Autowired
CacheManager cacheManager;
#Bean
public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() {
EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
return ehCacheManagerFactoryBean;
}
#Bean
public CacheManager cacheManager() {
EhCacheCacheManager cacheManager = new EhCacheCacheManager();
cacheManager.setCacheManager(ehCacheManagerFactoryBean().getObject());
return cacheManager;
}
#Bean
public MyBootstrapCacheLoaderFactory myBootstrapCacheLoaderFactory() {
return new MyBootstrapCacheLoaderFactory();
}
#Bean
public EhCacheFactoryBean ehCacheFactory() {
EhCacheFactoryBean ehCacheFactory = new EhCacheFactoryBean();
ehCacheFactory.setCacheManager(ehCacheManagerFactoryBean().getObject());
ehCacheFactory.setBootstrapCacheLoader(myBootstrapCacheLoaderFactory());
return ehCacheFactory;
}
}
Here is my implementation of BootstrapCacheLoader
package com.spinners.rest.config;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import com.spinners.rest.repositories.IdsMapRepository;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.bootstrap.BootstrapCacheLoader;
import net.sf.ehcache.bootstrap.BootstrapCacheLoaderFactory;
public class MyBootstrapCacheLoaderFactory extends BootstrapCacheLoaderFactory implements BootstrapCacheLoader {
#Autowired
private IdsMapRepository idsMapRepo;
public MyBootstrapCacheLoaderFactory() {
super();
}
#Override
public BootstrapCacheLoader createBootstrapCacheLoader(Properties properties) {
return new MyBootstrapCacheLoaderFactory();
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public boolean isAsynchronous() {
return false;
}
public void load(Ehcache ehCache) throws CacheException {
try {
// function for which I want to load data in cache
Map<String, String> idsMap = idsMapRepo.getIdsMap();
} catch (Exception e) {
e.printStackTrace();
}
}
}
any suggestions? thanks in advance friends.
Best Regards
Sajid

Related

Spring boot + MyBatis, multiple datasources and mappers (java and xml), getting "Invalid bound statement (not found)" error

I am trying to create a maven project to access Oracle database with more than one datasource configurations. Here is my code:
First DataSource Config:
package com.business.data.datasource;
import javax.sql.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
#Configuration
public class FirstDbConfig {
#Primary
#Bean(name = "firstDataSourceProperties")
#ConfigurationProperties("first.datasource")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
#Primary
#Bean(name = "firstDataSource")
#ConfigurationProperties(prefix = "first.datasource")
public DataSource dataSource(#Qualifier("firstDataSourceProperties") DataSourceProperties properties) {
return DataSourceBuilder.create().build();
}
#Bean(name = "firstSessionFactory")
#Primary
public SqlSessionFactoryBean firstSessionFactory(#Qualifier("firstDataSource") final DataSource firstDataSource)
throws Exception {
final SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(firstDataSource);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:./mapper/FirstDbMapper.xml"));
sqlSessionFactoryBean.setTypeAliasesPackage("com.business.data.model");
return sqlSessionFactoryBean;
}
}
Second DataSource Config:
package com.business.data.datasource;
import javax.sql.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
#Configuration
public class SecondDbConfig {
#Primary
#Bean(name = "secondDataSourceProperties")
#ConfigurationProperties("second.datasource")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
#Bean(name = "secondDataSource")
#ConfigurationProperties(prefix = "second.datasource")
public DataSource dataSource(#Qualifier("secondDataSourceProperties") DataSourceProperties properties) {
return DataSourceBuilder.create().build();
}
#Bean(name = "secondSessionFactory")
public SqlSessionFactoryBean secondSessionFactory(#Qualifier("secondDataSource") final DataSource firstDataSource)
throws Exception {
final SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(firstDataSource);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:./mapper/SecondDbMapper.xml"));
sqlSessionFactoryBean.setTypeAliasesPackage("com.business.data.model");
return sqlSessionFactoryBean;
}
}
First Mapper interface:
package com.business.data.repository;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import com.business.data.model.PersonDetail;
import org.springframework.stereotype.Repository;
#Repository
#Mapper
public interface FirstDbMapper {
public List<PersonDetail> getUserData(#Param("firstName") String firstName, #Param("lastName") String lastName);
}
Second Mapper interface:
package com.business.data.repository;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import com.business.data.model.PersonDetail;
import org.springframework.stereotype.Repository;
#Repository
#Mapper
public interface SecondDbMapper {
public List<PersonDetail> getStaffData(#Param("firstName") String firstName, #Param("lastName") String lastName);
}
src/main/resources/mapper/FirstMapper.xml
<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace must indicate mapper interface full package path . It is an alias here-->
<mapper namespace = "com.business.data.repository.FirstDbMapper">
<select id = "getUserData" parameterType = "map" resultMap = "personDetailMap">
SELECT *
FROM user
WHERE UPPER(first_name) LIKE UPPER(#{firstName}||'%')
AND UPPER(last_name) LIKE UPPER(#{lastName}||'%')
</select>
...
</mapper>
src/main/resources/mapper/SecondMapper.xml
<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace must indicate mapper interface full package path . It is an alias here-->
<mapper namespace = "com.business.data.repository.SecondDbMapper">
<select id = "getStaffData" parameterType = "map" resultMap = "personDetailMap">
SELECT *
FROM staff
WHERE UPPER(first_name) LIKE UPPER(#{firstName}||'%')
AND UPPER(last_name) LIKE UPPER(#{lastName}||'%')
</select>
...
</mapper>
Service class is like
#Autowired
FirstDbMapper firstDbMapper;
public List<PersonDetail> getUser(String fName, String lName) throws MyServiceException {
...
try {
userList = firstDbMapper.getUserData(fName, lName);
} catch (Exception e) {
...
}
return userList;
}
application.properties:
first.datasource.jdbc-url=jdbc:oracle:thin:#host01:1561:db1
first.datasource.username=user1
first.datasource.password=password1
second.datasource.jdbc-url=jdbc:oracle:thin:#host02:1561:db2
second.datasource.username=user2
second.datasource.password=password2
I also have #MapperScan("com.business.data.repository") in my spring boot application java.
I can only make one datasource work, which is the one with #Primary annotation. I swapped #Primary between the two configuration, always the one with #Primary worked, the other got "Invalid bound statement (not found)" error.
Can anyone help me out?
Thanks!
You can use the #MapperScan annotation on a configuration class to attach mappers to the different session factories. I find it convenient to place mappers in different packages like this:
#MapperScan(basePackages="mapper.package1", sqlSessionFactoryRef="firstSessionFactory")
#MapperScan(basePackages="mapper.package2", sqlSessionFactoryRef="secondSessionFactory")
The issue was resolved by using HikariDataSource.
#Primary
#Bean(name = FIRST_DATASOURCE)
#ConfigurationProperties(prefix = "first.datasource")
public DataSource dataSourceFirst() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}

Spring MVC Rest API - No qualifying bean of type 'com.app.dao.AdminsRepository'

This is my first experience using Spring MVC with REST API for having an angular front end. I created 3 configuration files:
Here is my ApplicationConfig
package com.app.config;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
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.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import javax.persistence.EntityManagerFactory;
#SuppressWarnings("unused")
#EnableWebMvc
#Configuration
#ComponentScan("com.app.controller")
#EnableJpaRepositories("com.app.dao")
public class ApplicationConfig {
#Bean
public InternalResourceViewResolver setup() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean
public DataSource dataSource() {
System.out.println("in datasoure");
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/db");
dataSource.setUsername("root");
dataSource.setPassword("");
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.app.model");
factory.setDataSource(dataSource());
return factory;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
}
MVC Config
package com.app.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#EnableWebMvc
#Configuration
public class MvcConfig implements WebMvcConfigurer {
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/views/", ".jsp");
}
#Bean
public InternalResourceViewResolver setup() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
WebInitializer
package com.app.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { ApplicationConfig.class, MvcConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
I also created a controller :
package com.app.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.app.dao.AdminsRepository;
import com.app.model.Admin;
#SuppressWarnings("unused")
#Controller
public class AdminsController {
#Autowired
private AdminsRepository adminsRepository;
#GetMapping("/admins")
#ResponseBody
public String getAllAdmins(Model model) {
return adminsRepository.findAll().toString();
}
#GetMapping("/admin/{id}")
#ResponseBody
public String getAdmin(#PathVariable("id") int id, Model model) {
return adminsRepository.findById((long) id).orElse(null).toString();
}
#PostMapping("/admin")
#ResponseBody
public String createAdmin(Admin admin, Model model) {
System.out.println(admin);
return adminsRepository.save(admin).toString();
}
}
The repository :
package com.app.dao;
//import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.app.model.Admin;
#Repository
public interface AdminsRepository extends JpaRepository <Admin, Long>{ }
And my model :
package com.app.model;
import java.io.Serializable;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.List;
#Entity
#Table(name="admins")
#NamedQuery(name="Admin.findAll", query="SELECT a FROM Admin a")
public class Admin implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private int id;
#Column(name="created_at")
private Timestamp createdAt;
private String email;
private String login;
private String password;
private String name;
private String surname;
// ... getters and setters + delegated methods
}
When I start running the application and open the browser I receive an error message:
No qualifying bean of type 'com.app.dao.AdminsRepository' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
G'day David,
Just breaking down the answer moiljter already gave you.
You can only #Autowire objects that are declared in packages being scanned for components.
Currently, your #ComponentScan annotation only includes your controller package:
#ComponentScan("com.app.controller")
Broaden the search slightly like so:
#ComponentScan("com.app")
Then it should pick up your AdminsRepository and hum nicely.
Cheers,
ALS
You need to add "com.app.dao" to the list of packages that Spring will scan for components (and maybe also "com.app.model" if any of those annotations are Spring ones), or just change it to scan "com.app" (which will include everything in your app.

Error creating Bean with name 'xmlViewResolver'

i am building a small web application with spring boot and theirfore i do not have an xml files as all configurations are handled by spring boot capabilities , however i decided to add an xmlViewResolver and gave the first priority. With that said i keep getting the following error:
Please Assist me in anyway possible , thank you
Configuration file is as follows:
package com.aubrey.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
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.InternalResourceViewResolver;
import org.springframework.web.servlet.view.XmlViewResolver;
#Configuration
#ComponentScan
#EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public InternalResourceViewResolver jspViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsps/");
resolver.setSuffix(".jsp");
return resolver;
}
#Bean(name = "messageSource")
public ReloadableResourceBundleMessageSource getMessageSource() {
ReloadableResourceBundleMessageSource resource = new ReloadableResourceBundleMessageSource();
resource.setBasename("classpath:messages");
resource.setDefaultEncoding("UTF-8");
return resource;
}
#Bean
public XmlViewResolver xmlViewResolver(){
XmlViewResolver resolver = new XmlViewResolver();
Resource resource = new ClassPathResource("/WEB-INF/Spring/views.xml");
resolver.setLocation(resource);
//xmlViewResolver().setOrder(1);
return resolver;
}
}
views.xml is as follows :
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="welcome" class="org.springframework.web.servlet.view.JstlView">
<property name="url" value="/WEB-INF/views/xml_welcome.jsp" />
</bean>
</beans>
</beans>
Home controller is as follows:
package com.aubrey.demo.controllers;
import com.aubrey.demo.data.entities.Project;
import com.aubrey.demo.data.entities.Sponsor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class HomeController {
#RequestMapping("/home")
public String goHome(Model model){
Project project = new Project();
project.setName("First Project");
project.setSponsor(new Sponsor("NASA", "555-555-5555", "nasa#nasa.com"));
project.setDescription("This is a simple project sponsored by NASA");
model.addAttribute("currentProject", project);
return "welcome";
}
}

spring batch admin ui not showing jobs that are be configured

I have integrated spring boot with spring-batch-admin successfully. I used the sample guide from spring-batch for setting up jobs. I added couple of more tasklets to the jobs. my UI shows only one job. I expect to see three of them. I also the expect the three jobs to have start/stop functionalities and take job parameters from UI.
I have pushed entire code here.. please feel free to issue pull requests if you have solutions or improvements.
Here is my job.xml located in src/main/resources/batch/jobs/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:batch="http://www.springframework.org/schema/batch"
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
<!-- This is the XML way to define jobs but it will be very handy if you already have jobs like this -->
<batch:job id="FirstJob" restartable="true">
<batch:step id="firstStep">
<batch:tasklet ref="firstTasklet" start-limit="1" />
</batch:step>
</batch:job>
<bean id="firstTasklet" class="hello.FirstTasklet">
<property name="property" value="${custom-property}" />
</bean>
</beans>
Here is my BatchConfiguration
package hello;
import javax.sql.DataSource;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
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.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
#Configuration
//#EnableBatchProcessing
public class BatchConfiguration {
#Autowired
public JobBuilderFactory jobBuilderFactory;
#Autowired
public StepBuilderFactory stepBuilderFactory;
#Autowired
public DataSource dataSource;
// #Value("#{jobParameters['file']:sample-data.csv}")
// String filename;
// tag::readerwriterprocessor[]
#Bean
//#StepScope
public FlatFileItemReader<Person> reader() {
FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>();
reader.setResource(new ClassPathResource("sample-data.csv"));
reader.setLineMapper(new DefaultLineMapper<Person>() {{
setLineTokenizer(new DelimitedLineTokenizer() {{
setNames(new String[] { "firstName", "lastName" });
}});
setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
setTargetType(Person.class);
}});
}});
return reader;
}
#Bean
public PersonItemProcessor processor() {
return new PersonItemProcessor();
}
#Bean
public JdbcBatchItemWriter<Person> writer() {
JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<Person>();
writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Person>());
writer.setSql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)");
writer.setDataSource(dataSource);
return writer;
}
// end::readerwriterprocessor[]
// tag::jobstep[]
#Bean
public Job importUserJob(JobCompletionNotificationListener listener) {
return jobBuilderFactory.get("importUserJob")
.incrementer(new RunIdIncrementer())
.listener(listener)
.flow(step1())
.end()
.build();
}
#Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.<Person, Person> chunk(10)
.reader(reader())
.processor(processor())
.writer(writer())
.build();
}
// end::jobstep[]
#Bean
#StepScope
public FailableTasklet tasklet(#Value("#{jobParameters[fail]}") Boolean failable) {
if(failable != null) {
return new FailableTasklet(failable);
}
else {
return new FailableTasklet(false);
}
}
public static class FailableTasklet implements Tasklet {
private final boolean fail;
public FailableTasklet(boolean fail) {
this.fail = fail;
}
#Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("Tasklet was executed");
if(fail) {
throw new RuntimeException("This exception was expected");
}
else {
return RepeatStatus.FINISHED;
}
}
}
}
screenshot of UI
Spring Batch Admin UI displays only the Jobs. You wouldn't see steps/tasklets in the UI as they cannot be run individually. But after you run your job, you could see the stats of each step that was performed in that job. Hope this helps.

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