Error when adding custom revision in Hibernate envers - spring-boot

When I add custom revision entity, I start getting error:
2020-12-13 00:22:29.418 ERROR 80983 --- [ost-startStop-1] o.s.b.web.embedded.tomcat.TomcatStarter : Error starting Tomcat context. Exception: org.springframework.beans.factory.UnsatisfiedDependencyException. Message: Error creating bean with name 'webSecurityConfig': Unsatisfied dependency expressed through field 'userDetailsService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userDetailsServiceImpl': Unsatisfied dependency expressed through field 'userRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Cannot create inner bean '(inner bean)#4384acd' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#4384acd': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: org/hibernate/resource/beans/spi/ManagedBeanRegistry
MyRevision:
package ...;
import org.hibernate.envers.DefaultRevisionEntity;
import org.hibernate.envers.RevisionEntity;
import javax.persistence.Entity;
#Entity
#RevisionEntity(MyRevisionListener.class)
public class MyRevision extends DefaultRevisionEntity {
private String username;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
}
MyRevisionListener:
package ...;
// import de.xxxxx.carorderprocess.models.User;
import org.hibernate.envers.RevisionListener;
// import org.springframework.security.core.Authentication;
// import org.springframework.security.core.context.SecurityContext;
// import org.springframework.security.core.context.SecurityContextHolder;
// import java.util.Optional;
public class MyRevisionListener implements RevisionListener {
#Override
public void newRevision(Object revisionEntity) {
/* String currentUser = Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.filter(Authentication::isAuthenticated)
.map(Authentication::getPrincipal)
.map(User.class::cast)
.map(User::getUsername)
.orElse("Unknown-User"); */
MyRevision audit = (MyRevision) revisionEntity;
audit.setUsername("dd");
}
}
WebSecurityConfig:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsServiceImpl userDetailsService;
UserDetailsServiceImpl:
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
UserRepository userRepository;
#Override
#Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));
return UserDetailsImpl.build(user);
}
}
UserRepository:
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
Boolean existsByUsername(String username);
}
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.0.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>de.xxxxxxx</groupId>
<artifactId>carorderprocess</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>carorderprocess</name>
<description>Demo project for Spring Boot</description>
<dependencyManagement>
<dependencies>
</dependencies>
</dependencyManagement>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</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-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-envers</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-envers</artifactId>
<version>5.4.25.Final</version>
</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>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

I think your problem could be related with the different dependencies in your pom.xml.
Please, first, remove the spring-data-envers dependency, unless you are querying your audit tables you do not need it. Even in that case, you can use Envers on its own to obtain that information if required.
Be aware that, as indicated in the comments of the answer from Sunit, you will need to remove the attribute repositoryFactoryBeanClass, it could not longer take the value EnversRevisionRepositoryFactoryBean. But you probably still need to include the #EnableJpaRepositories annotation.
Although I initially indicated that you can let Spring Boot manage your versions, due to the one of spring-boot-starter-parent, the framework is providing you versions of hibernate-xxx similar to 5.2.17.Final.
But, as you indicated, you need to use the method forRevisionsOfEntityWithChanges for querying your audit entities. As you can see in the java docs, that method was introduced in AuditQueryCreator in version 5.3.
As a consequence, you need to provide the following dependency:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-envers</artifactId>
<version>5.3.20.Final</version>
</dependency>
But in addition you also need to provide a compatible version of both hibernate-entitymanager and hibernate-core:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.3.20.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.3.20.Final</version>
</dependency>

From what I understood from all the comments above, your requirement is
to use Envers Auditing
and use method forRevisionsOfEntityWithChanges to get list of all revisions with what changed in them
Please start by doing these
Remove dependency of spring-data-envers library.
Just keep library hibernate-envers - version 5.4.23.Final also worked for me
Remove repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class from #EnableJpaRepositories annotation
All Repository classes should only extend from JpaRespository and NOT from RevisionRepository. You dont need RevisionRepository
You should be able to get your application up and running now.
Now coming back to the question, how to get all revisions with changes using forRevisionsOfEntityWithChanges method.
Create an AuditConfiguration class like this, to create the AuditReader bean
#Configuration
public class AuditConfiguration {
private final EntityManagerFactory entityManagerFactory;
AuditConfiguration(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
#Bean
AuditReader auditReader() {
return AuditReaderFactory.get(entityManagerFactory.createEntityManager());
}
}
In your AuditRevisionEntity class, add following annotation. Without this the serialization of this class wont work. e.g
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class AuditRevisionEntity extends DefaultRevisionEntity {
In your entity class add option withModifiedFlag = true to #Audited annotation. Without this you cannot get entity revisions with all changes. e.g
#Audited(withModifiedFlag = true)
public class Customer {
Modify your database table for this entity audit table and fields *_mod. e.g if you have a customer table with fields name, age, address columns, then add columns name_mod, age_mod, address_mod to the customer_audit table
Last, add following code in your service method to get audit revisions with changes
#Autowired
private AuditReader auditReader;
public List<?> getRevisions(Long id) {
AuditQuery auditQuery = auditReader.createQuery()
.forRevisionsOfEntityWithChanges(Customer.class, true)
.add(AuditEntity.id().eq(id));
return auditQuery.getResultList();
}
I will try to post the same code in Github sometime today, so that you can take a look at working code.

Your code looks fine. But it may not be sufficient to identify the root cause.
Looking at the exception it is clear that application is failing since it is not able to find bean dependency
Could you try following
Check your library imports first in your build.gradle or pom.xml. Generally you should not require any other Hibernate library other than Spring Boot Data JPA and Hibernate Envers
Try removing/disabling the Hibernate Envers audit code and library dependencies and see if can you get your application up and running. This will help you identify if error is due to Hibernate Envers or if your application code has other issues.
If above does not works, then please provide more information
Which version of Spring Boot are you on
What libraries have you imported (build.gradle or maven pom file)
What other Configurations you have in your project - do you have any other JPA configuration file or any other custom configuration related to Hibernate or JPA
What annotations are on the main application class
Directory structure of your Repository class, and the directory on which you do component scan (in case you have overridden it)

Related

NoSuchMethodException: com.aspectj.in.spring.boot.aop.aspect.auditlog.interceptor.LoggingInterceptorAspect.aspectOf()

I have a code that uses AspectJ. I use the compile-time weaving mode. During context initialization, I get an error. Although everything worked before that.
annotation
#Retention(RUNTIME)
#Target(METHOD)
#Documented
public #interface AuditAnnotation {
public String value() default "";;
}
LoggingInterceptorAspect
#Aspect
public class LoggingInterceptorAspect {
private LoggingService loggingService;
#Autowired
public LoggingInterceptorAspect(LoggingService loggingService) {
this.loggingService = loggingService;
}
#Pointcut("execution(private * *(..))")
public void privateMethod() {}
#Pointcut("#annotation(com.aspectj.in.spring.boot.aop.aspect.auditlog.annotation.AuditAnnotation)")
public void annotatedMethodCustom() {}
#Before("annotatedMethodCustom() && privateMethod()")
public void addCommandDetailsToMessage() throws Throwable {
ZonedDateTime dateTime = ZonedDateTime.now(ZoneOffset.UTC);
String message = String.format("User controller getUsers method called at %s", dateTime);
System.out.println("+++++++++++++++++++++++++");
loggingService.log(message);
}
}
LoggingInterceptorConfig (It is the error here.)
#Configuration
public class LoggingInterceptorConfig {
#Bean
public LoggingInterceptorAspect getAutowireCapableLoggingInterceptor() {
return Aspects.aspectOf(LoggingInterceptorAspect.class);
}
}
Here is an error in this line:
return Aspects.aspectOf(LoggingInterceptorAspect.class);
exception
ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getAutowireCapableLoggingInterceptor' defined in class path resource [com/aspectj/in/spring/boot/aop/aspect/auditlog/interceptor/config/LoggingInterceptorConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.aspectj.in.spring.boot.aop.aspect.auditlog.interceptor.LoggingInterceptorAspect]: Factory method 'getAutowireCapableLoggingInterceptor' threw exception; nested exception is org.aspectj.lang.NoAspectBoundException: Exception while initializing com.aspectj.in.spring.boot.aop.aspect.auditlog.interceptor.LoggingInterceptorAspect: java.lang.NoSuchMethodException: com.aspectj.in.spring.boot.aop.aspect.auditlog.interceptor.LoggingInterceptorAspect.aspectOf()
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.aspectj.in.spring.boot</groupId>
<artifactId>aspectj-in-spring-boot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>aspectj-in-spring-boot</name>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</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>com.nickwongdev</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.12.6</version>
<configuration>
<complianceLevel>11</complianceLevel>
<source>11</source>
<target>11</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>UTF-8</encoding>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<showWeaveInfo>true</showWeaveInfo>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
With the help of reflection, all public methods defined in LoggingInterceptorAspect.class. But why is null returned?
Maybe someone has some ideas why initialization is not happening LoggingInterceptorAspect.class
#Aspect
#Component
public class LoggingInterceptorAspect {
With #Component you register a bean of type LoggingInterceptorAspect in the application context.
#Bean
public LoggingInterceptorAspect getAutowireCapableLoggingInterceptor() {
Here with #Bean you register again another bean of type LoggingInterceptorAspect in the application context
Why register 2 beans of the same type when both are singletons?
Thanks for the MCVE on GitHub. Having access to it, helped me to easily identify your problems as follows:
Your dynamic #annotation() pointcut is quite broad, targeting all packages. I recommend to additionally add within() in order to limit the aspect scope.
In order to auto-inject the logger into the aspect, you want to use a setter instead of the constructor, because AspectJ aspects are expected to have default constructors.
Pointcut expression privateMethod() && publicMethod() will never match, because a method cannot be public and private at the same time. You want to use || instead. Or you can simply omit both pointcuts if you want to match both anyway. Also be careful, because in addition to public and private methods there are protected and package-scoped methods too, which you will be excluding if you are only targeting public and private ones.
Your aspect should look as follows:
package com.aspectj.in.spring.boot.aop.aspect.auditlog.interceptor;
import com.aspectj.in.spring.boot.service.LoggingService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
#Aspect
public class LoggingInterceptorAspect {
private LoggingService loggingService;
#Autowired
public void setLoggingService(LoggingService loggingService) {
this.loggingService = loggingService;
}
#Pointcut("execution(private * *(..))")
public void privateMethod() {}
#Pointcut("execution(public * *(..))")
public void publicMethod() {}
#Pointcut("#annotation(com.aspectj.in.spring.boot.aop.aspect.auditlog.annotation.AuditAnnotation)")
public void annotatedMethodCustom() {}
#Pointcut("within(com.aspectj.in.spring.boot..*)")
public void applicationScoped() {}
#Before("annotatedMethodCustom() && applicationScoped()")
//#Before("annotatedMethodCustom() && applicationScoped() && (privateMethod() || publicMethod())")
public void addCommandDetailsToMessage(JoinPoint joinPoint) throws Throwable {
ZonedDateTime dateTime = ZonedDateTime.now(ZoneOffset.UTC);
String message = String.format("User controller getUsers method called at %s", dateTime);
System.out.println("+++ " + joinPoint);
loggingService.log(message);
}
}
Update: I forgot to mention one possible problem in aspects which do not explicitly use execution() because they want to match all methods: When using #annotation() only, you are targetting both call() and execution() joinpoints, as you can see in the compiler log:
[INFO] Join point 'method-call(java.util.List com.aspectj.in.spring.boot.controller.UserController.getUsersInternal())' in Type 'com.aspectj.in.spring.boot.controller.UserController' (UserController.java:26) advised by before advice from 'com.aspectj.in.spring.boot.aop.aspect.auditlog.interceptor.LoggingInterceptorAspect' (LoggingInterceptorAspect.java:37)
[INFO] Join point 'method-execution(java.util.List com.aspectj.in.spring.boot.controller.UserController.getUsersInternal())' in Type 'com.aspectj.in.spring.boot.controller.UserController' (UserController.java:32) advised by before advice from 'com.aspectj.in.spring.boot.aop.aspect.auditlog.interceptor.LoggingInterceptorAspect' (LoggingInterceptorAspect.java:37)
CLASSPATH component C:\Program Files\JetBrains\IntelliJ IDEA 2018.3\plugins\maven\lib\maven3\boot\plexus-classworlds.license: java.util.zip.ZipException: zip END header not found
[INFO] Join point 'method-execution(java.util.List com.aspectj.in.spring.boot.service.impl.DefaultUserService.getMockUsers())' in Type 'com.aspectj.in.spring.boot.service.impl.DefaultUserService' (DefaultUserService.java:34) advised by around advice from 'org.springframework.cache.aspectj.AnnotationCacheAspect' (spring-aspects-5.3.9.jar!AbstractCacheAspect.class:64(from AbstractCacheAspect.aj))
This also leads to duplicate runtime logging output when omitting the && (privateMethod() || publicMethod()) condition:
+++ call(List com.aspectj.in.spring.boot.controller.UserController.getUsersInternal())
2021-09-04 16:11:41.213 INFO 17948 --- [o-auto-1-exec-1] sample-spring-aspectj : User controller getUsers method called at 2021-09-04T14:11:41.210203700Z
+++ execution(List com.aspectj.in.spring.boot.controller.UserController.getUsersInternal())
In order to avoid that, you should add a generic execution pointcut:
#Before("annotatedMethodCustom() && applicationScoped() && execution(* *(..))")

Parameter 0 of constructor in com.demo.service.NmpAppService required a bean named 'entityManagerFactory' that could not be found

I am trying to run a simple api flow in java spring and I am getting the following error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.nmp.bts.webapps.bsc.btbsc.service.NmpAppService required a bean named 'entityManagerFactory' that could not be found.
Action:
Consider defining a bean named 'entityManagerFactory' in your configuration.>
<Oct 25, 2019 10:37:51 AM EEST> <Notice> <Stdout> <BEA-000000> <WARN: The method class org.apache.commons.logging.impl.SLF4JLogFactory#release() was invoked.>
<Oct 25, 2019 10:37:51 AM EEST> <Notice> <Stdout> <BEA-000000> <WARN: Please see http://www.slf4j.org/codes.html#release for an explanation.>
<Oct 25, 2019 10:37:51 AM EEST> <Error> <Deployer> <BEA-149265> <Failure occurred in the execution of deployment request with ID "48455312047066616" for task "216" on [partition-name: DOMAIN]. Error is: "weblogic.application.ModuleException: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available"
weblogic.application.ModuleException: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
at weblogic.application.internal.ExtensibleModuleWrapper.start(ExtensibleModuleWrapper.java:140)
at weblogic.application.internal.flow.ModuleListenerInvoker.start(ModuleListenerInvoker.java:124)
at weblogic.application.internal.flow.ModuleStateDriver$3.next(ModuleStateDriver.java:237)
at weblogic.application.internal.flow.ModuleStateDriver$3.next(ModuleStateDriver.java:232)
at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45)
Truncated. see log file for complete stacktrace
Caused By: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1207)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
Truncated. see log file for complete stacktrace
I want to mention that I`ve tried all kind of stuffs starting from the other similar topics on stackoverflow, to change dependency and nothing worked for me.
Controller class: NmpAppController.java
#RestController
#RequestMapping("/api")
public class NmpAppController {
private final NmpAppService nmpAppService;
#Autowired
public NmpAppController(NmpAppService nmpAppService) {
this.nmpAppService = nmpAppService;
}
#GetMapping("/nmp-apps")
public List<NmpApp> getAllNmps() {
try {
return nmpAppService.getAllNmpApps();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Service class: NmpAppService.java
#Service
public class NmpAppService {
private final NmpAppRepository nmpAppRepository;
public NmpAppService(NmpAppRepository nmpAppRepository) {
this.nmpAppRepository = nmpAppRepository;
}
public NmpApp save(final NmpApp nmpApp) {
final NmpApp nmpAppToBeSaved = nmpApp;
NmpApp result = nmpAppRepository.saveAndFlush(nmpAppToBeSaved);
return result;
}
public NmpApp update(final NmpApp nmpApp) {
final NmpApp nmpAppitToBeSaved = nmpApp;
NmpApp result = nmpAppRepository.saveAndFlush(nmpAppToBeSaved);
return result;
}
public List<NmpApp> getAllNmpApps() {
return nmpAppRepository.findAll();
}
Repository class: NmpAppRepository.java
#Repository
public interface NmpAppRepository extends JpaRepository<NmpApp, Long> {
}
Domain class NmpApp.java
#Entity
#Table(name = "NMP_APP")
public class NmpApp {
#Id
#Column(name = "SEQ_NO")
private Long seqNo;
#Column(name = "HIST_DATE")
private Long histDate;
public NmpApp() {
}
public NmpApp(Long seqNo, Long histDate) {
this.seqNo = seqNo;
this.histDate = histDate;
}
public Long getSeqNo() {
return seqNo;
}
public void setSeqNo(Long seqNo) {
this.seqNo = seqNo;
}
public Long getHistDate() {
return histDate;
}
public void setHistDate(Long histDate) {
this.histDate = histDate;
}
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>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.nmp.bts.webapps.bsc</groupId>
<artifactId>nm-app</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>bt-bsc</name>
<description>BSC</description>
<packaging>war</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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>
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-data-jdbc</artifactId>-->
<!--</dependency>-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<archive>
<manifest>
<addDefaultImplementationEntries>false</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
Spring boot main class: Application.java
#EnableTransactionManagement
#SpringBootApplication(exclude = {HibernateJpaAutoConfiguration.class})
public class Application extends SpringBootServletInitializer implements WebApplicationInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.getSessionCookieConfig().setHttpOnly(false);
super.onStartup(servletContext);
}
}
Later Edit: I uploaded the application.properties file
#Basic Spring Boot Config for Oracle
spring.datasource.url= jdbc:oracle:thin:#//:/
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.jndi-name=jdbc/DEV_ADF_APPLDS
#hibernate config
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
spring.main.allow-bean-definition-overriding=true
I want to be able to perform simple CRUD operations on a database via swagger api caller (code shows only getAll but I do have the rest of code tho).
Usually happens when Spring is missing the spring-boot-starter-data-jpa since Spring infers the EntityManager from the Spring Data JPA which has an out of the box implementation for Hibernate ORM.
Adding the following to project pom.xml usually solves this problem
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
But in your case is available so the offending code is
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
Change to
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
Instead of spring-boot-starter-data-rest, try using the following
"org.springframework.boot:spring-boot-starter-data-jpa"
"org.springframework.boot:spring-boot-starter-jdbc"
Later edit: Also, don't forget to add #EnableTransactionManagement on the spring boot main class or on the database configuration class

Difficulty to configure Activiti into a Springboot application api

First of all is it a viable thing to embed Activiti into an API type application for use within that application or should Activiti be run standalone?
The error below is due to bean definition but I'm not sure where the beans should be defined and how - if thats correct approach for version 6. Our standards with Springhboot 2 is to annotate beans in java rather than xml context
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-04-10 21:17:43.924 ERROR 19516 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field runtimeService in ma.cvmeeting.workflow.WorkflowApplication$MyrestController required a bean of type 'org.activiti.engine.RuntimeService' 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.activiti.engine.RuntimeService' in your configuration.
Process finished with exit code 0
code:
import org.activiti.engine.RuntimeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#SpringBootApplication
public class WorkflowApplication {
public static void main(String[] args) {
SpringApplication.run(WorkflowApplication.class, args);
}
#RestController
public static class MyrestController{
#Autowired
private RuntimeService runtimeService;
#GetMapping("/start-process")
public String startProcess() {
runtimeService.startProcessInstanceByKey("Potulerauneoffre");
return "Process started. Number of currently running"
+ "process instances = "
+ runtimeService.createProcessInstanceQuery().count();
}
}
pom.xml:
<project>
<groupId>ma.cvmeeting</groupId>
<artifactId>workflow</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>workflow</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>7-201802-EA</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.h2database</groupId>
<artifactId>h2database</artifactId>
<version>1.0.20061217</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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
There are two ways to initialize the engine when you embed it in your spring based application:
1.) let spring initialize it for you so you can use all the engine services right away without need of any configuration. this requires activiti-spring-boot-starter as dependency.
2.) You initialize engine by your self and provide the services beans from #Configuration class. for this you will require only activiti-engine core as dependency
The reason your application cannot find the RuntimeService because you are trying the second approach add the below dependency in your pom.xml and remove the engine one
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
</dependency>
you should follow documentation for more help.
We recommend activiti 7 core if you are planning to use spring boot 2.x and the use of the new APIs. This is great time if you want to get involved with the new APIs and project initiatives
You could write a #Configuration class and define Activiti services, like this :
#Configuration
public class ActivityConfig {
#Autowired
DataSource dataSource;
#Bean
public DataSourceTransactionManager getTransactionManager() {
return new DataSourceTransactionManager(dataSource);
}
#Bean
public ProcessEngineConfigurationImpl getProcessEngineConfiguration() {
SpringProcessEngineConfiguration res = new SpringProcessEngineConfiguration();
res.setDataSource(dataSource);
res.setTransactionManager(getTransactionManager());
return res;
}
#Bean
public ProcessEngineFactoryBean getProcessEngine() {
ProcessEngineFactoryBean res = new ProcessEngineFactoryBean();
res.setProcessEngineConfiguration(getProcessEngineConfiguration());
return res;
}
#Bean
public RepositoryService getRepositoryService() throws Exception {
return getProcessEngine().getObject().getRepositoryService();
}
#Bean
public FormService getFormService() throws Exception {
return getProcessEngine().getObject().getFormService();
}
#Bean
public TaskService getTaskService() throws Exception {
return getProcessEngine().getObject().getTaskService();
}
#Bean
public RuntimeService getRuntimeService() throws Exception {
return getProcessEngine().getObject().getRuntimeService();
}
#Bean
public HistoryService getHistoryService() throws Exception {
return getProcessEngine().getObject().getHistoryService();
}
#Bean
public IdentityService getIdentityService() throws Exception {
return getProcessEngine().getObject().getIdentityService();
}
}

Error creating bean with name 'gemfireCache': FactoryBean threw exception on object creation

I am trying to create an "employee" Region and put some data into it. But, I am getting Exception below:
[warn 2018/12/27 17:15:46.518 IST tid=0x1] Exception
encountered during context initialization - cancelling refresh
attempt: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'gemfireConfiguration': Injection of
resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'gemfireCache': FactoryBean threw exception on
object creation; nested exception is java.lang.NoClassDefFoundError:
it/unimi/dsi/fastutil/ints/Int2ObjectOpenHashMap
[warn 2018/12/27 17:15:46.519 IST tid=0x1] Invocation of
destroy method failed on bean with name 'gemfireCache':
org.apache.geode.cache.CacheClosedException: A cache has not yet been
created.
[error 2018/12/27 17:15:46.522 IST tid=0x1] Caught exception
while allowing TestExecutionListener
[org.springframework.test.context.web.ServletTestExecutionListener#c667f46]
to prepare test instance
[com.gemfire.demo.Gemfire1ApplicationTests#48bfb884]
Domain class
#Region("employee")
public class Employee {
#Id
public String name;
public double salary;
...
}
Repository class
#Repository
public interface EmployeeRepository extends CrudRepository<Employee, String> {
Employee findByName(String name);
}
Configuration class
#Configuration
#ComponentScan
#EnableGemfireRepositories(basePackages = "com.gemfire.demo")
public class GemfireConfiguration {
#Autowired
EmployeeRepository employeeRepository;
#Bean
Properties gemfireProperties() {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", "SpringDataGemFireApplication");
gemfireProperties.setProperty("mcast-port", "0");
gemfireProperties.setProperty("log-level", "config");
return gemfireProperties;
}
#Bean
#Autowired
CacheFactoryBean gemfireCache() {
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setProperties(gemfireProperties());
return gemfireCache;
}
#Bean(name="employee")
#Autowired
LocalRegionFactoryBean<String, Employee> getEmployee(final GemFireCache cache) {
LocalRegionFactoryBean<String, Employee> employeeRegion = new LocalRegionFactoryBean<String, Employee>();
employeeRegion.setCache(cache);
employeeRegion.setClose(false);
employeeRegion.setName("employee");
employeeRegion.setPersistent(false);
employeeRegion.setDataPolicy(DataPolicy.PRELOADED);
return employeeRegion;
}
}
POM.XML
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</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.data</groupId>
<artifactId>spring-data-gemfire</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.9.0</version>
</dependency>
Adding additional tips with your above GemFire/Spring JavaConfig configuration class above.
Given you are using Spring Data Kay (implied by your use of the Spring Boot 2.0.x parent POM, i.e. org.springframework.boot:spring-boot-dependencies; see here), then you could be using Spring Data GemFire's (relatively) new and convenient Annotation-based configuration model.
By doing so, your GemfireConfiguration class above would become...
#PeerCacheApplication
#EnableGemfireRepositories(basePackages = "com.gemfire.demo")
class GemfireConfiguration {
#Bean(name="employee")
LocalRegionFactoryBean<String, Employee> getEmployee(GemFireCache cache) {
LocalRegionFactoryBean<String, Employee> employeeRegion =
new LocalRegionFactoryBean<String, Employee>();
employeeRegion.setCache(cache);
employeeRegion.setClose(false);
employeeRegion.setDataPolicy(DataPolicy.PRELOADED);
return employeeRegion;
}
}
A few things to keep in mind:
#PeerCacheApplication is meta-annotated with #Configuration so you do not need the explicit Spring #Configuration annotation on the configuration class.
#PeerCacheApplication allows you to adjust the GemFire log-level (along with other logging configuration) using the logLevel annotation attribute. Similarly, you can set the log-level using the corresponding property, spring.data.gemfire.cache.log-level in a Spring Boot application.properties file (see here). There are many other attributes and corresponding properties (e.g. name) you can use to adjust and customize other configuration.
While String-based package names are supported on #EnableGemfireRepositories and similar annotations, we generally prefer and recommend users to use the type-safe variant basePacakgeClasses. You only need to refer to a single type from each top-level package where your application Repositories are kept.
The explicit #Autowired annotation is not needed on your bean definitions. You do not need to explicit inject the EmployeeRepository in the configuration class to have it initialized; just inject it into the #Service class where it will be used.
For convenience, the name ("employee") of the Region bean definition on your LOCAL "employee" Region, will also be used as the name of the Region, so employeeRegion.setName("employee") is unnecessary.
You should not combine LocalRegionFactoryBean.setPersistent(:boolean) with LocalRegionFactoryBean.setDataPolicy(:DataPolicy) since the DataPolicy is going to take precedence.
While #ComponentScan is perfectly acceptable and even convenient in development, I generally do not prefer nor recommend users to use component-scanning. It is usually always better to be explicit.
As stated in the comments, you chould remove <relativePath/> from your parent definition in your application Maven POM file.
Final note, as of this post, Spring Boot 2.0.8.RELEASE is the latest release.
As for your classpath issues, if you are using Maven correctly, then Maven should take care of pulling in the correct transitive dependencies.
You can refer to the many examples I have in this repo for further clarification.
Hope this helps!
As mentioned in comments, the error shows some dependencies (java.lang.NoClassDefFoundError: it/unimi/dsi/fastutil/ints/Int2ObjectOpenHashMap) are missing. Please add corresponding dependencies in your pom.xml

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