I've got a Spring boot application with enabled autoconfiguration.
My application is divided into 4 modules core, model, rest and repository.
Repository module uses Spring data and Hibernate. It is a module that contains all class entities and all spring data repositories.
The problem is that my application cannot find EntityManagerFactory that to my mind should be created by autoconfiguration based on added Hibernate dependency.
What error I get is:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
here is my main gradle configuration:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.5.RELEASE")
}
}
plugins {
id 'java'
id 'idea'
id 'org.springframework.boot' version "2.1.0.RELEASE"
id 'io.spring.dependency-management' version "1.0.6.RELEASE"
id 'net.ltgt.apt' version '0.9'
}
group 'com.wat'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile project(':core')
compile project(':model')
compile project(':rest')
compile project(':repository')
compile group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '2.1.0.RELEASE'
compile group: 'io.jsonwebtoken', name: 'jjwt', version: '0.9.1'
compile "org.mapstruct:mapstruct-jdk8:1.2.0.Final"
apt "org.mapstruct:mapstruct-processor:1.2.0.Final"
testCompile group: 'junit', name: 'junit', version: '4.12'
}
allprojects {
apply plugin: "java"
repositories {
mavenCentral()
}
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.2'
compile group: 'org.springframework', name: 'spring-context', version: '5.1.1.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.1.0.RELEASE'
compile "org.mapstruct:mapstruct-jdk8:1.2.0.Final"
compile "org.mapstruct:mapstruct-processor:1.2.0.Final"
}
}
my main class
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
My repository module gradle file:
plugins {
id 'net.ltgt.apt'
}
dependencies {
compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '2.1.2.RELEASE'
compile group: 'org.hibernate', name: 'hibernate-core', version: '5.3.7.Final'
compile 'mysql:mysql-connector-java:8.0.13'
compile project(":model")
testCompile group: 'junit', name: 'junit', version: '4.12'
}
and my repository module configuration class:
#Configuration
#EnableJpaRepositories(basePackages = "com.wat.zpm.repository")
#EnableTransactionManagement
#EnableAutoConfiguration
public class RepositoryConfiguration {
}
According to what I found out is that spring autoconfigurer automatically creates bean EntityManagerFactory based on classpath classes so everything should work fine with given annotations.
What is more autoconfiguration logging says that HibernateJpaAutoConfiguration was matched.
The class that misses the EntityManagerFactory:
#Repository
public class UserRepositoryServiceImpl implements UserRepositoryService {
private final UserEntityMapper userMapper;
private final UserRepository userRepository;
public UserRepositoryServiceImpl(UserEntityMapper userMapper, UserRepository userRepository1) {
this.userMapper = userMapper;
this.userRepository = userRepository1;
}
}
UserRepository is a interface that extends JpaRepository
I've made a research and couldn't found annotation or dependency that my project could possibly miss.
You are missing #ComponantScan in RepositoryConfiguration class.
here is the great explanation of componentscan annotation.
Related
In my spring-boot project, I try to register my project as eureka discovery client. This is my simple code:
package com.my.simpleService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// Compiler error: org.springframework.cloud cannot be resolved
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
#EnableDiscoveryClient
#SpringBootApplication
public class MyServiceApplication {
public static void main(String[] args) {
SpringApplication.run(MyServiceApplication.class, args);
}
}
I get compiler error: import org.springframework.cloud cannot be resolved.
Following is my gradle.build file:
plugins {
id 'org.springframework.boot' version '2.5.3'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.my.simpleService'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}
ext {
set('springCloudVersion', '2020.0.0')
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation group: 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:3.0.3'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
test {
useJUnitPlatform()
}
Why I get that compiler error? What am I missing?
You need to add the spring-cloud-commons, e.g. update your dependencies to the following:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-commons'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
I want to use spock in my spring-boot project (using groovy, not java). I have some projects with spock already working in java 8 and lower versions of gradle but I can't find documentation about the newest versions.
This is my OLD build.gradle
buildscript {
ext {
springBootVersion = '2.1.0.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'groovy'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.test'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
implementation('org.springframework.boot:spring-boot-starter-data-mongodb')
implementation('org.springframework.boot:spring-boot-starter-web')
implementation('org.codehaus.groovy:groovy')
testImplementation('org.springframework.boot:spring-boot-starter-test')
testCompile(
'junit:junit:4.12',
'org.codehaus.groovy:groovy-all:2.4.4',
'org.spockframework:spock-core:1.2-groovy-2.4',
'cglib:cglib:2.2',
'org.spockframework:spock-spring:1.2-groovy-2.4',
)
}
this works and I can create spock tests but when I create a project with java 11 and gradle 6.4, nothing works anymore (the gradle syntax is way different and the spock libraries don't work anymore),
this is my CURRENT (and failing) build.gradle:
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'groovy'
}
group = 'com.test'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.codehaus.groovy:groovy'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'org.postgresql:postgresql'
testImplementation("org.spockframework:spock-core") {
exclude group: "org.codehaus.groovy", module: "groovy-all"
}
testImplementation group: 'org.spockframework', name: 'spock-spring', version: '2.0-M3-groovy-3.0'
testImplementation(enforcedPlatform("org.spockframework:spock-bom:2.0-M1-groovy-2.5"))
}
test {
useJUnitPlatform()
}
With this, nothing works but the gradle build doesn't found the spock-spring libraries.
How can I apply the spock libraries to spring boot with the newest versions of java and gradle?
Think you got into a muddle of Groovy Versions with the dependencies:
I tested with this build:
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'groovy'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
jcenter()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.codehaus.groovy:groovy:3.0.5'
testImplementation('org.spockframework:spock-core:2.0-M3-groovy-3.0')
testImplementation('org.spockframework:spock-spring:2.0-M3-groovy-3.0')
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
And this test ran and passed:
package test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.context.ApplicationContext
import spock.lang.Specification
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = Application)
class ContextSpec extends Specification {
#Autowired
ApplicationContext context
def "context is as expected"() {
expect:
context
context.getBean("echoService")
}
}
(Obviously, I had an echoService in my context)
For completeness, here's the service:
package test
import org.springframework.stereotype.Service
#Service("echoService")
class EchoService {
String echo(String value) {
value?.reverse()
}
}
The controller:
package test
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.RestController
#RestController
class EchoController {
final EchoService echoService
EchoController(EchoService echoService) {
this.echoService = echoService
}
#RequestMapping(
value = "/echo/{message}",
method = RequestMethod.GET,
produces = MediaType.TEXT_PLAIN_VALUE
)
String doEcho(#PathVariable String message) {
return echoService.echo(message)
}
}
And the application class:
package test
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
#SpringBootApplication
class Application {
static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And proof 😉
➜ curl localhost:8080/echo/hello
olleh%
In order to use ShedLock with Cassandra, I need the CqlSession to create a CassandraLockProvider, according to the docs.
However, I always get the following error:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.datastax.oss.driver.api.core.CqlSession' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
This full minimal example below reproduces the issue:
src/main/kotlin/com/foo/cqlsessioninjection/application.kt
package com.foo.cqlsessioninjection
import com.datastax.oss.driver.api.core.CqlSession
import net.javacrumbs.shedlock.core.LockProvider
import net.javacrumbs.shedlock.provider.cassandra.CassandraLockProvider
import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.scheduling.annotation.EnableScheduling
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component
#SpringBootApplication
#EnableScheduling
#EnableSchedulerLock(defaultLockAtMostFor = "PT23H")
class CqlSessionInjection
#Configuration
class SchedulerConfiguration {
#Bean
fun lockProvider(cqlSession: CqlSession): LockProvider {
return CassandraLockProvider(cqlSession)
}
}
#Component
class SomeTask {
#Scheduled(cron = "*/1 * * * * ?") // every second
#SchedulerLock(name = "some_task")
fun runSomeTask() {
println("some task")
}
}
fun main(args: Array<String>) {
runApplication<CqlSessionInjection>(*args)
}
build.gradle
buildscript {
ext {
kotlinVersion = '1.3.71'
springBootVersion = '2.2.6.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
}
}
apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.foo'
version = '1.0.0-SNAPSHOT'
sourceCompatibility = 1.8
compileKotlin {
kotlinOptions {
freeCompilerArgs = ["-Xjsr305=strict"]
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
freeCompilerArgs = ["-Xjsr305=strict"]
jvmTarget = "1.8"
}
}
repositories {
mavenCentral()
}
dependencies {
implementation group: 'net.javacrumbs.shedlock', name: 'shedlock-spring', version: '4.9.1'
implementation group: 'net.javacrumbs.shedlock', name: 'shedlock-provider-cassandra', version: '4.9.1'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-cassandra'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'
implementation group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8'
implementation group: 'org.jetbrains.kotlin', name: 'kotlin-reflect'
implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.3.3'
compile group: 'com.google.guava', name: 'guava', version: '23.3-jre'
testCompile group: 'org.cassandraunit', name: 'cassandra-unit-spring', version: '3.11.2.0'
testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test'
annotationProcessor group: 'org.springframework.boot', name: 'spring-boot-configuration-processor'
}
task downloadDependencies(type: Exec) {
configurations.testRuntime.files
commandLine 'echo', 'Downloaded all dependencies'
}
compileKotlin.dependsOn(processResources)
compileJava.dependsOn(processResources)
settings.gradle
rootProject.name = 'CqlSessionInejction'
src/test/kotlin/com/foo/cqlsessioninjection/integration/ContextTest.kt
package com.foo.cqlsessioninjection.integration
import org.cassandraunit.spring.CassandraDataSet
import org.cassandraunit.spring.CassandraUnitDependencyInjectionTestExecutionListener
import org.cassandraunit.spring.EmbeddedCassandra
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.TestExecutionListeners
import org.springframework.test.context.junit4.SpringRunner
#RunWith(SpringRunner::class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#TestExecutionListeners(
listeners = [CassandraUnitDependencyInjectionTestExecutionListener::class],
mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
)
#CassandraDataSet(value = ["cql/cql_session_injection.cql"], keyspace = "shedlock")
#EmbeddedCassandra
class ContextTest {
#Test
fun `test task`() {
println("starting to sleep")
Thread.sleep(4000)
println("done sleeping")
}
}
src/test/resources/application.yml
spring:
data:
cassandra:
contact-points: localhost
port: 9142
keyspace_name: shedlock
src/test/resources/cql/cql_session_injection.cql
DROP KEYSPACE IF EXISTS shedlock;
CREATE KEYSPACE shedlock
WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':1};
CREATE TABLE shedlock.lock (
name text PRIMARY KEY,
lockUntil timestamp,
lockedAt timestamp,
lockedBy text
);
The doc you've referenced points out that a CqlSession bean has to be created but it does not really explain how you get there. I would report that as a documentation issue to this project to make it a bit more explicit.
You need Spring Boot 2.3 to get Cassandra v4 support. The version you are using (2.2x) uses Cassandra v3 and a completely different API.
We have decided to use RedisLockRegistry by adding spring-integration to my project developed with Spring boot 1.5.7.
But when we add spring-integration-starter and spring-integration-redis to the project, quartz gives an error.
If I change the spring-context with spring-context-support or if I add spring-context-support, it is not an error.
Why should I add spring-context-support instead of spring-context or change it either?
gradle
buildscript {
ext {
springBootVersion = '1.5.7.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
allprojects {
repositories {
mavenCentral()
mavenLocal()
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: "io.spring.dependency-management"
apply plugin: 'maven'
apply plugin: 'idea'
sourceCompatibility = 1.8
idea {
module {
sourceDirs += file('build/classes/main/generated')
generatedSourceDirs += file('build/classes/main/generated')
}
}
dependencies {
compileOnly 'org.projectlombok:lombok'
testCompile 'org.springframework.boot:spring-boot-starter-test'
testCompile 'com.h2database:h2'
testCompile 'org.springframework.security:spring-security-test'
}
}
group = 'com.example.redislock'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
compileJava.dependsOn(processResources)
dependencies {
compile 'org.springframework.boot:spring-boot-starter-aop'
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.boot:spring-boot-starter-integration'
compile 'org.quartz-scheduler:quartz:2.3.0'
compile 'org.springframework:spring-core'
//compile 'org.springframework:spring-context'
compile 'org.springframework:spring-context-support'
compile 'org.springframework.integration:spring-integration-redis'
compile 'org.hibernate:hibernate-java8'
compile 'io.springfox:springfox-swagger2:2.6.1'
compile 'io.springfox:springfox-swagger-ui:2.6.1'
compile 'org.springframework.boot:spring-boot-starter-actuator'
compile 'org.flywaydb:flyway-core:4.2.0'
compileOnly 'org.springframework.boot:spring-boot-configuration-processor'
runtime 'org.postgresql:postgresql:42.2.1'
}
This is error giving class:
package com.example.redislock.DemoRedisLockGradle.scheduler;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
#Configuration
public class ExampleScheduler {
#Bean(name = "asdTrigger")
public CronTriggerFactoryBean triggerFactoryBean(#Qualifier("asdJobFactory") JobDetailFactoryBean jobFactory) {
return createTriggerFactoryBean(jobFactory.getObject());
}
#Bean(name = "asdJobFactory")
public JobDetailFactoryBean asd() {
return createJobDetailFactoryBean(ExampleJob.class);
}
CronTriggerFactoryBean createTriggerFactoryBean(JobDetail jobDetail) {
CronTriggerFactoryBean ctFactory = new CronTriggerFactoryBean();
ctFactory.setName("Example Factory");
ctFactory.setCronExpression("0 0/1 * * * ?");
ctFactory.setJobDetail(jobDetail);
return ctFactory;
}
JobDetailFactoryBean createJobDetailFactoryBean(Class<? extends Job> jobClass) {
JobDetailFactoryBean factory = new JobDetailFactoryBean();
factory.setJobClass(jobClass);
return factory;
}
}
It cant find quartz.CronTriggerFactoryBean and quartz.JobDetailFactoryBean
Thanks in advance
I found the solution. If ı exclude spring-data-redis on spring-integration-redis it's not need adding spring-context-support
compile('org.springframework.boot:spring-boot-starter-integration')
compile('org.springframework.integration:spring-integration-redis') {
exclude group: 'org.springframework.data', module: 'spring-data-redis'
}
I am getting the below exception.
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
Below is the my build.gradle
buildscript {
ext {
springBootVersion = '1.4.0.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
ext {
aemVersion='1.0.25'
avroVersion = '1.8.0'
springWSVersion = '2.2.1.RELEASE'
jibxMinorVersion = "5"
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'spring-boot'
jar {
baseName = 'abc'
version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.7
targetCompatibility = 1.7
repositories {
flatDir {
dirs "${rootDir}/lib"
}
mavenLocal()
mavenCentral()
maven {
name 'springFramework'
url 'https://mvnrepository.com/artifact'
}
}
dependencies {
compile('org.apache.camel:camel-spring-boot-starter:2.17.2')
compile('org.apache.camel:camel-kafka:2.17.2')
compile group: 'org.apache.camel', name: 'camel-avro', version: '2.17.2'
compile "org.springframework.ws:spring-ws-core:$springWSVersion"
compile ('org.jdom:jdom:2.0.2')
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.4'
compile group: 'org.springframework.integration', name: 'spring-integration-kafka', version: '2.0.0.RELEASE'
compile group: 'org.springframework.integration', name: 'spring-integration-core', version: '4.3.1.RELEASE'
compile group: 'org.apache.kafka', name: 'kafka_2.10', version: '0.8.0'
compile ('org.jibx:jibx-run:1.2.5'){
exclude group: 'bcel', module: 'bcel'
}
testCompile ('org.jibx:jibx-extras:1.2.5'){
exclude group: 'bcel', module: 'bcel'
}
compile("org.springframework.boot:spring-boot-starter")
testCompile('org.springframework.boot:spring-boot-starter-test')
}
My application is a non-web application. I run it from command line and use following code.
#SpringBootApplication
public class MyApplication implements CommandLineRunner{
#Autowired
private Executor routeExecutor;
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
System.out.println("Running Application from run method..");
this.routeExecutor.executeRoute();
}
}
I don't want tomcat. I have looked for this exception and it is a common one but I do not want to add "spring-boot-starter-web" dependency because it is a non-web application. Please help me out
Spring Boot has incorrectly guessed that you're trying to build a web application based on what you've got on the classpath. You can correct it by using SpringApplicationBuilder and setting web to false in your main method:
public static void main(String[] args) {
new SpringApplicationBuilder(MyApplication.class).web(false).run(args);
}