Springboot JdbcTemplate Autowired failed - spring

I'm trying to access database using springboot, however spring application throws an exception below.
Error creating bean with name 'welcomeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.jdbc.core.JdbcTemplate com.mysite.soLexiconWebSpring.jsp.WelcomeController.dataSource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.jdbc.core.JdbcTemplate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Which I think is mainly
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.jdbc.core.JdbcTemplate] found for dependency
that indicates that no bean is created from application config file.
However I googled for a while and got no luck. Can anybody tell me how to inject JdbcTemplate Correctly?
Here is my POM:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<!-- Your own application should inherit from spring-boot-starter-parent -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.0.2.RELEASE</version>
</parent>
<artifactId>soLexiconWebSpring</artifactId>
<groupId>com.mysite</groupId>
<packaging>war</packaging>
<name>Spring Boot Web JSP Sample</name>
<description>Spring Boot Web JSP Sample</description>
<version>0.0.1-SNAPSHOT</version>
<url>http://projects.spring.io/spring-boot/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>http://www.spring.io</url>
</organization>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
<m2eclipse.wtp.contextRoot>/</m2eclipse.wtp.contextRoot>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
</configuration>
</plugin>
</plugins>
</build>
</project>
Application.properties
spring.view.prefix=/WEB-INF/jsp/
spring.view.suffix=.jsp
application.message=Hello SuperLucky
#spring.datasource basic database parameter
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/so_lexicon
spring.datasource.username=xxx
spring.datasource.password=xxx
#set data pooling provider to org.apache.tomcat
spring.datasource.type = org.apache.tomcat.jdbc.pool.DataSource
#tomcat datasource settings
spring.datasource.tomcat.initial-size=20
spring.datasource.tomcat.max-wait=2000
spring.datasource.tomcat.max-active=100
spring.datasource.tomcat.max-idle=16
spring.datasource.tomcat.min-idle=4
spring.datasource.tomcat.test-on-connect=true
spring.datasource.tomcat.test-on-borrow=true
spring.datasource.tomcat.test-on-return=true
Application
package com.mysite.soLexiconWebSpring.jsp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class SampleWebJspApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SampleWebJspApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleWebJspApplication.class, args);
}
}
Controller
package com.mysite.soLexiconWebSpring.jsp;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.mysite.soLexiconWebSpring.jsp.beans.FullLexiconRowBean;
import com.mysite.soLexiconWebSpring.jsp.beans.LoginTokenBean;
import com.mysite.soLexiconWebSpring.jsp.dao.LexiconDaoImpl;
import com.mysite.soLexiconWebSpring.jsp.utils.DBUtils;
#Controller
public class WelcomeController {
#Value("${application.message:Hello World}")
private String message = "Hello World";
#Autowired
private JdbcTemplate dataSource;
#Autowired
private DBUtils dbUtils;
#RequestMapping("/soLexiconWebSpring")
public String welcome(Map<String, Object> model) {
model.put("time", new Date());
model.put("message", this.message);
return "welcome";
}
#RequestMapping("/soLexiconWebSpring/login")
public String login(#RequestParam("username") String username, #RequestParam("password") String password, Map<String, Object> model)
{
LoginTokenBean loginToken = new LoginTokenBean();
loginToken.setUsername(username);
loginToken.setPassword(password);
model.put("loginToken", loginToken);
LexiconDaoImpl lexRowDao = new LexiconDaoImpl(dataSource);
List<FullLexiconRowBean> result = lexRowDao.getLexiconRow(1, 5);
if(result != null) model.put("result", result);
else model.put("result", dbUtils.getLastException().toString());
dbUtils.setLastException(new Exception("A B C"));
model.put("dbUtils", dbUtils);
return "lexicon";
}
}

Thanks for #mrkemelpanic, I updated my project to springboot 2.0.4 (with some effort), and it finally works. So it might be a 1.0.2 bug or something.
Thanks.

Related

Unable to import #HystrixCommand

I am learning microservices. Therefore to ensure fault tolerance I wanted to use hystrix.
I use springboot with maven for this implementation. I followed a tutorial to make the implementation and have tried adding various dependencies in the pom.xml. However it wasn't successful. The #HystrixCommand is unable to be imported for the usage. I have attached the sample error shown here below. My micro service application code looks like below.
My Pom.XML file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>io.javabrains</groupId>
<artifactId>movie-catalog-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>movie-catalog-service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2020.0.3</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
The main method
package io.javabrains.moviecatalogservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
#SpringBootApplication
#EnableEurekaClient
#EnableHystrix
public class MovieCatalogServiceApplication {
#Bean
#LoadBalanced
public RestTemplate getRestTemplate() {
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setConnectTimeout(3000);
return new RestTemplate(clientHttpRequestFactory);
}
public static void main(String[] args) {
SpringApplication.run(MovieCatalogServiceApplication.class, args);
}
}
The controller/ resource class
package io.javabrains.moviecatalogservice.resources;
import com.netflix.discovery.DiscoveryClient;
import io.javabrains.moviecatalogservice.models.CatalogItem;
import io.javabrains.moviecatalogservice.models.Movie;
import io.javabrains.moviecatalogservice.models.Rating;
import io.javabrains.moviecatalogservice.models.UserRating;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
//How to make it REST... Just add the annotation
//So whenever a request is made, it checks the controller for any action to be done
#RestController
//Further to say springboot to treat this as api which is accessible at /catalog/something
#RequestMapping("/catalog")
public class MovieCatalogResource {
#Autowired //I am basically telling spring that somebody has a BEAN somewhere, offsitre restTempltae//GET ME THT THING
private RestTemplate restTemplate;
//
// #Autowired
// private DiscoveryClient client;
//FOR WEB CLIENT
#Autowired
private WebClient.Builder webClientBuilder;
#RequestMapping("/{userId}") //userId is a variable and it will passed
#HystrixCommand(fallbackMethod = "getFallBackCatalog")//teliing hsyutrix that getCatalog shouldnt brak the limit. If it breaks, call getFallBackCatalog
public List<CatalogItem> getCatalog(#PathVariable("userId") String userId){
UserRating ratings = restTemplate.getForObject("http://RATING-DATA-SERVICE/ratingsdata/user/" + userId, UserRating.class);
return ratings.getRatings().stream().map(rating -> {
System.out.println(rating.getMovieId());
Movie movie = restTemplate.getForObject("http://MOVIE-INFO-SERVICE/movies/"+rating.getMovieId(), Movie.class);
return new CatalogItem(movie.getName() , "Test", rating.getRating());
})
.collect(Collectors.toList());
}
public List<CatalogItem> getFallBackCatalog(#PathVariable("userId") String userId){
return Arrays.asList(new CatalogItem("No movie", "", 0));//returning default list
}
}
However, the problem that I get is that I am unable to import the #HystrixCommand as its not getting recognized
Add version in this dependency. Just like this
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>

if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for step scope

I am using Spring Boot v2.6.2 and Spring Batch and getting below error:
ustom destroy method 'close' on bean with name 'compositeItemWriter' threw an exception: org.springframework.beans.factory.support.ScopeNotActiveException: Error creating bean with name 'scopedTarget.xmlDelegateItemWriter': Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for step scope
MainApp.java
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.configuration.annotation.StepScope;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.support.CompositeItemWriter;
import org.springframework.batch.item.support.builder.CompositeItemWriterBuilder;
import org.springframework.batch.item.xml.StaxEventItemWriter;
import org.springframework.batch.item.xml.builder.StaxEventItemWriterBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.oxm.xstream.XStreamMarshaller;
import javax.sql.DataSource;
import java.util.*;
#SpringBootApplication
#EnableBatchProcessing
public class CompositeItemWriterJobApplication {
#Autowired
private JobBuilderFactory jobBuilderFactory;
#Autowired
private StepBuilderFactory stepBuilderFactory;
#Bean(destroyMethod="")
#StepScope
public FlatFileItemReader<Customer> compositeWriterItemReader(#Value("#{jobParameters['customerFile']}") Resource inputFile) {
return new FlatFileItemReaderBuilder<Customer>()
.name("compositeWriterItemReader")
.resource(inputFile)
.delimited()
.names("firstName", "middleInitial", "lastName", "address", "city", "state", "zip", "email")
.targetType(Customer.class)
.build();
}
#Bean(destroyMethod="")
#StepScope
public StaxEventItemWriter<Customer> xmlDelegateItemWriter(#Value("#{jobParameters['outputFile']}") Resource outputFile){
Map<String, Class> aliases = new HashMap<>();
aliases.put("customer", Customer.class);
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setAliases(aliases);
marshaller.afterPropertiesSet();
return new StaxEventItemWriterBuilder<Customer>()
.name("customerItemWriter")
.resource(outputFile)
.marshaller(marshaller)
.rootTagName("customers")
.build();
}
#Bean
public JdbcBatchItemWriter<Customer> jdbcDelgateItemWriter(DataSource dataSource) {
return new JdbcBatchItemWriterBuilder<Customer>()
.namedParametersJdbcTemplate(new NamedParameterJdbcTemplate(dataSource))
.sql("INSERT INTO CUSTOMER (first_name, middle_initial, last_name, address, city, state, email) " +
"VALUES(:firstName,:middleInitial, :lastName, :address, :city, :state, :zip, :email)")
.beanMapped()
.build();
}
#Bean
public CompositeItemWriter<Customer> compositeItemWriter() throws Exception {
return new CompositeItemWriterBuilder<Customer>()
.delegates(Arrays.asList(xmlDelegateItemWriter(null),
jdbcDelgateItemWriter(null)))
.build();
}
#Bean
public Step compositeWriterStep() throws Exception {
return this.stepBuilderFactory.get("compositeWriterStep")
.<Customer, Customer>chunk(10)
.reader(compositeWriterItemReader(null))
.writer(compositeItemWriter())
.build();
}
#Bean
public Job compositeWriterJob() throws Exception {
return this.jobBuilderFactory.get("compositeWriterJob")
.start(compositeWriterStep())
.build();
}
public static void main(String[] args) {
SpringApplication.run(CompositeItemWriterJobApplication.class,
"customerFile=/data/customer.csv",
"outputFile=/output/customer.xml");
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>composite-item-writer-job</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>composite-item-writer-job</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.18</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Note: I also used #Scope(value = "step", proxyMode = ScopedProxyMode.TARGET_CLASS), but no luck.
Bean
#Bean
public org.springframework.batch.core.scope.StepScope stepScope() {
final StepScope stepScope = new org.springframework.batch.core.scope.StepScope();
stepScope.setAutoProxy(true);
return stepScope;
}
application.yml
spring:
batch:
initialize-schema: always
datasource:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
username: 'root'
password: 'root'
platform: mysql
main:
allow-bean-definition-overriding: true
Things are still not working!
I encountered the same problem. For me, the solution was to add “#StepScope” on the methods calling the method with “#StepScope” and the jobParameters. In this example, I would try to annotate the method compositeItemWriter with “#StepScope”. You will probably need to do it with jdbcDelgateItemWriter.
#Bean
#StepScope
public CompositeItemWriter<Customer> compositeItemWriter() throws Exception {
return new CompositeItemWriterBuilder<Customer>()
.delegates(Arrays.asList(xmlDelegateItemWriter(null),
jdbcDelgateItemWriter(null)))
.build();
}

Modular #Configuration/#Bean in Spring Boot

I'm making a MicroServices based project so I have more the one Spring Boot projects in my workspace. I need to configure restOperations in some of then but I want to configure once for all the project that needs. So I'm trying to add my #Configuration class to a jar and import in each MS projects.
The problem is, when I execute the MS project in my server, I receive this error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field restOperations in com.epavanellio.base.business.controller.BusinessController required a bean of type 'org.springframework.web.client.RestOperations' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'org.springframework.web.client.RestOperations' in your configuration.
Here I have my Rest configuration class:
package com.epavanellio.base.restConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
//#Component
#Configuration
public class SimpleRestConfiguration {
final CloseableHttpClient httpClient = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy())
.build();
#Bean
public RestOperations createRestTemplate(final ClientHttpRequestFactory clientHttpRequestFactory){
return new RestTemplate(clientHttpRequestFactory);
}
#Bean
public ClientHttpRequestFactory createHttpRequestFactory (#Value("${rest.connect.timeout}") final int connectTimeout,
#Value("${rest.read.timeout}") final int readTimeout) {
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setConnectTimeout(connectTimeout);
clientHttpRequestFactory.setReadTimeout(readTimeout);
clientHttpRequestFactory.setHttpClient(httpClient);
return clientHttpRequestFactory;
}
}
I imported the .jar (dpdc-rest) with has the SimpleRestConfiguration class in my MS project POM:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.epavanellio.base</groupId>
<artifactId>ms-manager-business</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ms-manager-business</name>
<description>Validate business logic. A microservice based project. </description>
<packaging>war</packaging>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.epavanellio.base</groupId>
<artifactId>domain</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.epavanellio.base</groupId>
<artifactId>dpdc-rest</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.epavanellio.base</groupId>
<artifactId>dpdc-custom-exception-handler</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<finalName>ms-manager-business</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
and in my MS application class is like this:
package com.epavanellio.base.business;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import com.epavanellio.base.restConfig.SimpleRestConfiguration;
//#SpringBootApplication(scanBasePackages={"com.epavanellio.base", "com.epavanellio.base.restConfig"})
//#Import(SimpleRestConfiguration.class)
//#ComponentScan({"com.epavanellio.base", "com.epavanellio.base.restConfig"})
#ComponentScan("com.epavanellio.base")
#EntityScan("com.epavanellio.base.domain")
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
#SpringBootApplication
public class BusinessApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(BusinessApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(BusinessApplication.class);
}
}
as you can see commented, I already tried to my make my runtime "see" my configuration class in diffrent ways:
First I tried to add (scanBasePackages={"com.epavanellio.base", "com.epavanellio.base.restConfig"}) after my annotation #SpringBootApplication, but the same error occurs. Then I tried to add specifically the SimpleRestConfiguration class package to the #ComponentScan annotation(for this, I uncommented the #Component annotation in SimpleRestConfiguration class), but the same error occurs. At least I tried to use #Import, but in this case I receive the error:
java.io.FileNotFoundException: class path resource [com/epavanellio/base/restConfig/SimpleRestConfiguration.class] cannot be opened because it does not exist
does any one know how can I make my application class to "see" my
#Configuration class?
The problem was Maven, for some reason maven was no recognizing my jar.
so I made a new dependency project, with a new name but same same SimpleRestConfiguration class. I imported the new .Jar to my MS and then works fine.
My application become like this:
#ComponentScan("com.epavanellio.base")
#EntityScan("com.epavanellio.base.domain")
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
#SpringBootApplication
public class UserApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(UserApplication.class);
}
}

Spring Boot with Apache CXF and CDI

When using Apache's CXF JAX-RS Spring Boot starter with the CXF CDI dependency (cxf-integration-cdi), Spring fails trying to do the autowiring because it only supports JSR 330 and not CDI. Is there a way to get CDI to work with Spring Boot?
Code:
package com.ibm.test.webservices;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
#ApplicationPath("/")
#Path("/")
public class TestWebServices extends Application {
public static void main(String[] args) {
SpringApplication.run(
TestWebServices.class,
"--cxf.path=/",
"--cxf.jaxrs.classes-scan=true",
"--cxf.jaxrs.classes-scan-packages=" +
TestWebServices.class.getPackage().getName()
);
}
#Inject
#Any
private Instance<InvokerInterface> impl;
#GET
#Produces("text/plain")
#Path("/")
public String helloWorld() {
return impl.get().invoke();
}
public interface InvokerInterface {
String invoke();
}
#Named
#Default
public static class Implementation1 implements InvokerInterface {
public String invoke() {
return "Hello World 1\n";
}
}
#Named
public static class Implementation2 implements InvokerInterface {
public String invoke() {
return "Hello World 2\n";
}
}
}
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ibm.test</groupId>
<artifactId>test-spring-boot-with-cdi</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Test Spring Boot with Apache CXF and CDI</name>
<!-- We need to use cxf-spring-boot-starter-jaxrs 3.2.0 because of https://issues.apache.org/jira/browse/CXF-7237
At the time of writing this code, the latest available version in Maven central
is 3.1.7 so we need to use the Apache snapshot repository. -->
<repositories>
<repository>
<id>apache.snapshots</id>
<name>Apache Development Snapshot Repository</name>
<url>https://repository.apache.org/content/repositories/snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxrs</artifactId>
<version>3.2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-integration-cdi</artifactId>
<version>3.1.11</version>
</dependency>
</dependencies>
<!-- Required for a standalone JAR: -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Exception:
2017-07-28 16:32:59.527 ERROR 9630 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field impl in com.ibm.test.webservices.TestWebServices required a bean of type 'javax.enterprise.inject.Instance' that could not be found.
Action:
Consider defining a bean of type 'javax.enterprise.inject.Instance' in your configuration.
[WARNING]
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:527)
at java.lang.Thread.run(Thread.java:785)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testWebServices': Unsatisfied dependency expressed through field 'impl'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.enterprise.inject.Instance<com.ibm.test.webservices.TestWebServices$InvokerInterface>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#javax.inject.Inject(), #javax.enterprise.inject.Any()}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
at com.ibm.test.webservices.TestWebServices.main(TestWebServices.java:22)
... 6 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.enterprise.inject.Instance<com.ibm.test.webservices.TestWebServices$InvokerInterface>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#javax.inject.Inject(), #javax.enterprise.inject.Any()}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
... 25 more
The key insight is that Spring autowiring (e.g. scanBasePackages on #SpringBootApplication, #ComponentScan, etc.) must be avoided. The following worked:
TestSpringBootApplication.java:
package com.test.webservices;
import org.apache.cxf.cdi.CXFCdiServlet;
import org.jboss.weld.environment.se.Weld;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
#SpringBootApplication
// #ServletComponentScan only occurs with an embedded web server, and this is
// needed for Tomcat:
// https://docs.jboss.org/weld/reference/latest/en-US/html/environments.html#_tomcat
#ServletComponentScan(basePackageClasses = { org.jboss.weld.environment.servlet.Listener.class })
public class TestSpringBootApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(TestSpringBootApplication.class);
app.addInitializers(new ApplicationContextInitializer<ConfigurableApplicationContext>() {
#Override
public void initialize(ConfigurableApplicationContext applicationContext) {
new Weld().initialize();
}
});
app.run(args);
}
#Bean
public ServletRegistrationBean cxfServletRegistration() {
// http://cxf.apache.org/docs/using-cxf-and-cdi-11-jsr-346.html
ServletRegistrationBean registration = new ServletRegistrationBean(new CXFCdiServlet(), "/*");
registration.setLoadOnStartup(1);
return registration;
}
}
TestWebServicesApplication.java:
package com.test.webservices;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/")
public class TestWebServicesApplication extends Application {
}
TestWebServices.java:
package com.test.webservices;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.Vetoed;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
#Path("/")
public class TestWebServices {
#Inject
#Any
private Instance<InvokerInterface> impl;
#GET
#Produces("text/plain")
#Path("/")
public String helloWorld() {
return impl.get().invoke();
}
public interface InvokerInterface {
String invoke();
}
public static class Implementation1 implements InvokerInterface {
public String invoke() {
return "Hello World 1\n";
}
}
#Vetoed
public static class Implementation2 implements InvokerInterface {
public String invoke() {
return "Hello World 2\n";
}
}
}
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>test-spring-boot-with-cdi</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>Test Spring Boot with Apache CXF and CDI</name>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!-- We need to use cxf-spring-boot-starter-jaxrs 3.2.0 because of https://issues.apache.org/jira/browse/CXF-7237
At the time of writing this code, the latest available version in Maven central
is 3.1.7 so we need to use the Apache snapshot repository. -->
<repositories>
<repository>
<id>apache.snapshots</id>
<name>Apache Development Snapshot Repository</name>
<url>https://repository.apache.org/content/repositories/snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxrs</artifactId>
<version>3.2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-integration-cdi</artifactId>
<version>3.1.11</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>2.4.4.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se</artifactId>
<version>2.4.4.Final</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
</dependency>
</dependencies>
<!-- Required for a standalone JAR: -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
src/main/resources/META-INF/beans.xml:
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
</beans>
src/main/resources/META-INF/context.xml:
<!-- Required for Tomcat: https://docs.jboss.org/weld/reference/latest/en-US/html/environments.html#_tomcat -->
<Context>
<Resource name="BeanManager" auth="Container"
type="javax.enterprise.inject.spi.BeanManager" factory="org.jboss.weld.resources.ManagerObjectFactory" />
</Context>
To use JAXB in addition to JSON, it seems that CXF's JAXRSCdiResourceExtension doesn't find any #Providers, so I also added a CDI Extension that creates JacksonJaxbJsonProvider as an AnnotatedType (this also seems to require that the JAX-RS Application object does not override getClasses or getSingletons and instead auto-discovers all #Paths):
package com.test;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
public class RegisterCDIBeans implements javax.enterprise.inject.spi.Extension {
public void beforeBeanDiscovery(#Observes BeforeBeanDiscovery bbd, BeanManager beanManager) {
final AnnotatedType<?> annotatedType = beanManager.createAnnotatedType(JacksonJaxbJsonProvider.class);
bbd.addAnnotatedType(annotatedType, annotatedType.toString());
}
}
And then register the CDI extension in src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension:
com.test.RegisterCDIBeans
you need to create the bean or use #Autowired to inject javax.enterprise.inject.Instance class into TestWebServices. you can create the bean into ApplicationContaxt.xml and use #Autowired #Qualifier to inject class.

Spring Batch using MongoDB with Spring Boot throws Cannot determine embedded database driver class for database type NONE

I am Getting following exception on server-startup for Spring Batch application using mongodb. Please note I have correct configuration for Mongo DB but application still trying to load JDBC data source.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>batch</groupId>
<artifactId>batch-commerce</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<name>Pallete Commerce with SpringBoot on JBoss</name>
<properties>
<spring-batch.version>4.0.0.M1</spring-batch.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- Spring MVC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- We need to include the javax.servlet API specs, the implementation will be provided by Wildfly / JBoss-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- MongoDB for database -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- Spring Security for authentication-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<!-- JSTL for JSP
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>-->
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- Spring Batch -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>openshift</id>
<build>
<finalName>boot</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<outputDirectory>webapps</outputDirectory>
<warName>boot</warName>
</configuration>
</plugin>
</plugins>
</build>
</profile>
package com.batch;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
import org.springframework.boot.web.support.SpringBootServletInitializer;
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.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.data.MongoItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.core.io.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import com.batch.StudentDTO;
import com.mongodb.MongoClient;
import org.springframework.batch.core.Step;
#SpringBootApplication
#EnableBatchProcessing
public class BatchApplication extends SpringBootServletInitializer {
private static final Logger logger = LoggerFactory.getLogger(BatchApplication.class);
#Bean
FlatFileItemReader<StudentDTO> fileReader(#Value("resources/import_file.csv") Resource in) throws Exception {
return new FlatFileItemReaderBuilder<StudentDTO>().name("file-reader").resource(in).targetType(StudentDTO.class)
.delimited().delimiter(",").names(new String[] { "emailAddress", "name", "purchasedPackage" }).build();
}
#Bean
public MongoDbFactory mongoDbFactory() throws Exception {
return new SimpleMongoDbFactory(new MongoClient(), "shop");
}
#Bean
public MongoTemplate mongoTemplate() throws Exception {
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory());
return mongoTemplate;
}
#Bean
public ItemWriter<StudentDTO> writer() {
MongoItemWriter<StudentDTO> writer = new MongoItemWriter<StudentDTO>();
try {
writer.setTemplate(mongoTemplate());
} catch (Exception e) {
logger.error(e.toString());
}
writer.setCollection("student");
return writer;
}
// #Bean
// JdbcBatchItemWriter<StudentDTO> jdbcWriter(DataSource ds) {
// return new JdbcBatchItemWriterBuilder<StudentDTO>()
// .dataSource(ds)
// .sql("insert into STUDENT(EMAIL, NAME, PURCHASE_PACKAGE)
// values(:emailAddress, :name, :purchasedPackage)")
// .beanMapped()
// .build();
// }
//
#Bean
Job job(JobBuilderFactory jbf, StepBuilderFactory sbf, ItemReader<StudentDTO> reader,
ItemWriter<StudentDTO> writer) {
Step step1 = sbf.get("product-file").<StudentDTO, StudentDTO>chunk(100).reader(reader).writer(writer).build();
return jbf.get("productFeedJob").incrementer(new RunIdIncrementer()).start(step1).build();
}
public static void main(String[] args) {
SpringApplication.run(BatchApplication.class, args);
}
}
spring:
application:
name: shop
data:
mongodb:
host: ${OPENSHIFT_MONGODB_DB_HOST}
port: ${OPENSHIFT_MONGODB_DB_PORT}
database: ${MONGODB_DATABASE}
username: ${OPENSHIFT_MONGODB_DB_USERNAME}
password: ${OPENSHIFT_MONGODB_DB_PASSWORD}
mvc:
view:
suffix: .jsp
prefix: /views/
server:
error:
whitelabel:
enabled: true
security:
oauth2:
client:
client-id: ${SECURITY_OAUTH2_CLIENT_ID}
client-secret: ${SECURITY_OAUTH2_CLIENT_SECRET}
grant-type: ${SECURITY_OAUTH2_CLIENT_GRANT_TYPE}
access-token-uri: ${SECURITY_OAUTH2_CLIENT_ACCESS_TOKEN_URI}
logging.level:
org.springframework.web: DEBUG
org.hibernate: ERROR
org.springframework.security: INFO
Error: Description:
Cannot determine embedded database driver class for database type NONE
Action:
If you want an embedded database please put a supported one on the
classpath. If you have database settings to be loaded from a
particular profile you may need to active it (no profiles are
currently active).
12:37:00,953 ERROR [org.jboss.msc.service.fail] (ServerService Thread
Pool -- 79) MSC000001: Failed to start service
jboss.undertow.deployment.default-server.default-host."/batch-commerce-1.0.0":
org. jboss.msc.service.StartException in service
jboss.undertow.deployment.default-server.default-host."/batch-commerce-1.0.0":
java.lang.RuntimeException:
org.springframework.beans.factory.UnsatisfiedDepe ndencyException:
Error creating bean with name
'org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration':
Unsatisfied dependency expressed through field 'dataSources': Error c
reating bean with name 'dataSource' defined in class path resource
[org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Tomcat.class]:
Bean instantiation via factory method failed; nes ted exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [org.apache.tomcat.jdbc.pool.DataSource]: Factory method
'dataSource' threw exception; nested exception is
org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException:
Cannot determine embedded database driver class for database type
NONE. If you want an embedded databa se please put a supported one on
the classpath. If you have database settings to be loaded from a
particular profile you may need to active it (no profiles are
currently active).; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'dataSource' defined in class path resource
[org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$
Tomcat.class]: Bean instantiation via factory method failed; nested
exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.apache.tomcat.jdbc.pool.DataSource]: F
actory method 'dataSource' threw exception; nested exception is
org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException:
Cannot determine embedded database dri ver class for database type
NONE. If you want an embedded database please put a supported one on
the classpath. If you have database settings to be loaded from a
particular profile you may need to act ive it (no profiles are
currently active).
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:85)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
at org.jboss.threads.JBossThread.run(JBossThread.java:320)
I feel the spring jdbc dependency with batch is expecting you to supply datasource details. If you ignore the DataSourceAutoConfiguration this should run.
Add this with your spring boot applicaiton class
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})

Resources