I have a Spring Boot console application that uses Spring Data.
I have a simple jpa repository
public interface MyRepository extends JpaRepository<MyEntity, Integer> {
}
and an entity defined like this
import javax.validation.constraints.Min;
// ....
#Entity
#Table(schema = "mySchema", name = "myTable")
public class MyEntity {
// ...
#Column(nullable = false)
#Min(100)
private Integer group;
// ...
}
When I save this entity
myRepository.save(myEntity);
pom:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.0.Final</version>
</dependency>
</dependencies>
I expect to see a validation error because group is 0 but I don't see any issue and at the database the value of a newly added row is 0. What else do I need to do to enable validation?
Try with import javax.validation.Valid; #Valid
When the target argument fails to pass the validation, Spring Boot throws a MethodArgumentNotValidException exception.
Adding this to pom did the trick
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Related
I am a new to Spring boot so I apologize if this is a easily resolved issue.
I am seeing a problem running springboot after I added a #Transient final variable to my entity. Essentially I need a constant variable in my class that stores a string that I do not want stored in the database.
Adding in just this variable causes no issues with spring and the program runs as expected however, if I add a getter for this variable Springboot raises the exception:
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 javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
Here is my code causing the issue (I am not even calling the getter yet and it's causing this issue):
#ApiModel(description = "This class represents a device with its basic information.")
#Entity
#Table(name = "device")
public class Device {
#Transient
private final String invisibleName = "Jwfqp4bbqiFzRLcFVV3qf";
#Id
#ApiModelProperty(notes = "A UUID number to identify the device in the system.")
private String deviceId;
#ApiModelProperty(notes = "The device IP address of the device, this is also a unique identifier.")
private String ipAddress;
public Device() {
}
#Id
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceUuid) {
this.deviceId = deviceUuid;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public String getInvisibleName(){
return invisibleName;
}
}
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 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.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>project-name</artifactId>
<version>0.0.1</version>
<packaging>war</packaging>
<name>projectName</name>
<description>Project Name</description>
<properties>
<java.version>1.8</java.version>
<log4j2.version>2.16.0</log4j2.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
One important thing that I've noticed is that I can resolve the building issue by adding a useless parameter to the the getter such as:
public String getInvisibleName(int temp){
return invisibleName;
}
but If possible I would like to get to the bottom of this issue so I don't have useless parameters in my getter.
Let me know if I need to provide any additional information.
Thanks
Thank you all for your help. I removed the extraneous #Id on the 'getDeviceId' and moved the #Transient to the getter. I also noticed that apparently Spring had created an 'invisibleName' entry in the database causing a mismatch with my #Entity class. I removed the field from the database and that resolved the issue.
You should move the #Transient annotation above the getInvisibleName() method.
I have a springboot application that ingests an application.properties via #ConfigurationProperties and #PropertySource("classpath:application.properties"). My desire is to reload these properties on the fly for the purposes of support. When I POST to http://localhost:8080/actuator/refresh I get a 200 OK response but the body is empty, which I think implies no #RefreshScopes have been refreshed but I'm not sure. I have read and viewed most docs and SO while trying various things but haven't managed to reload a new value.
Here is my app:
application.properties:
# suppress inspection "UnusedProperty" for whole file
# the name of Camel
camel.springboot.name = IntegrationsCamel
# how often to trigger the timer (millis)
myPeriod = 2000
spring.main.allow-bean-definition-overriding=true
# to turn off Camel info in (/actuator/info)
management.info.camel.enabled=false
# to configure logging levels
logging.level.org.springframework = INFO
logging.level.org.apache.camel.spring.boot = INFO
logging.level.org.apache.camel.impl = DEBUG
logging.level.sample.camel = DEBUG
# Environment
integration.env = DEV
spring.application.name = integration
spring.config.import=aws-parameterstore:
# Client API Auth -- Set by Instance
integration.client.auth.key = tempclientkey
integration.client.auth.secret = tempclientsecret
# Client API Credentials -- Set by Instance
integration.client.endpoint = https://127.0.0.2
integration.client.port = 6060
# AWS Paramstore Config
aws.paramstore.enabled=true
aws.paramstore.prefix=/integration
aws.paramstore.defaultContext=application
aws.paramstore.profile-separator=_
# AWS OAuth
cloud.aws.credentials.instance-profile=true
cloud.aws.credentials.profile-name=default
cloud.aws.credentials.access-key=${AWS_ACCESS_KEY_ID}
cloud.aws.credentials.secret-key=${AWS_SECRET_ACCESS_KEY}
# Non EC2 vars (remove when running live)
cloud.aws.stack.auto=false
cloud.aws.region.static=eu-west-1
AWS_EC2_METADATA_DISABLED=true
logging.level.com.amazonaws.util.EC2MetadataUtils=error
logging.level.com.amazonaws.internal.InstanceMetadataServiceResourceFetcher=error
# DB Vars
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.url=jdbc:sqlserver://${RDS_HOSTNAME:my-server-domain.com}:${RDS_PORT:1337};databaseName=${RDS_DB_NAME:MYDB}
spring.datasource.username=${RDS_USERNAME:readuser}
spring.datasource.password=${RDS_PASSWORD:${read_pass}}
spring.jpa.properties.hibernate.default_schema=dbo
# Actuator Management
management.endpoints.enabled-by-default=false
management.endpoint.refresh.enabled=true
management.endpoints.web.exposure.include=refresh
All of these are successfully pulled in to the bean
package com.Integration.Configuration;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.event.EventListener;
#Getter
#Setter
#RefreshScope
#Configuration
public class ApplicationProperties {
#Value("${integration.env}")
private String env;
#Value("${spring.datasource.url}")
private String DB_URL;
#Value("${rds-username}")
private String DB_USERNAME;
#Value("${rds-password}")
private String DB_ENCRYPTED_PASSWORD;
#Value("${oauth2.key}")
private String OAuth2Key;
#Value("${oauth2.secret}")
private String OAuth2Secret;
#Value("${integration.client.endpoint}")
private String ClientAPIEndpoint;
#Value("${integration.client.port}")
private String ClientAPIPort;
#Value("${integration.client.auth.key}")
private String ClientAPIKey;
#Value("${integration.client.auth.secret}")
private String ClientAPISecret;
public ApplicationProperties() {}
#SuppressWarnings("unused")
#EventListener(RefreshScopeRefreshedEvent.class)
public void onRefresh(RefreshScopeRefreshedEvent event) {
// todo: Bug-#01 #RefreshScope actuator/refresh not updating #Values
System.out.println(this.ClientAPIEndpoint);
}
}
The event listener fires without issue too and it will successfully print the value from application.properties. I have debugged main below and all values are populated without issue.
I suspect the issue is here but I'm not sure what I'm doing wrong in main()
package com.Integration;
import com.Integration.AutoLoader.RouteBuilderAutoLoader;
import com.Integration.Configuration.ApplicationProperties;
import com.Integration.Scheduler.TasksScheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.apache.camel.CamelContext;
import org.apache.camel.impl.DefaultCamelContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.Objects;
#SpringBootApplication
#RefreshScope
#EnableScheduling
public class Integration {
public static String SERVER_ADDR;
protected static CamelContext context;
public static void main(String[] args) throws Exception {
// Spring Boot App Entry
ConfigurableApplicationContext appContext = SpringApplication.run(Integration.class, args);
// Get ApplicationProperties
ApplicationProperties properties = appContext.getBean(ApplicationProperties.class);
SERVER_ADDR = (Objects.equals(properties.getEnv(), "DEV")) ? "0.0.0.0" : "localhost";
// Start Camel Context Engine
context = new DefaultCamelContext();
// Feed Camel our defined routes & start
RouteBuilderAutoLoader.loadRoutes(context);
context.start();
}
}
The last thing I'm unsure of is if I have the necessary dependencies or if I'm missing something here.
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress MavenPackageUpdate -->
<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.Integration</groupId>
<artifactId>Integration</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Integration</name>
<description>Generic API Integration App</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.6.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.6.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.4.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>9.4.1.jre8</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- AWS/Cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>io.awspring.cloud</groupId>
<artifactId>spring-cloud-aws-context</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>io.awspring.cloud</groupId>
<artifactId>spring-cloud-starter-aws-parameter-store-config</artifactId>
<version>2.4.0</version>
</dependency>
<!-- Camel 3.14.1 Latest LTS version -->
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-bom</artifactId>
<version>3.14.1</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core-languages</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-bean</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-rest</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-direct</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-netty-http</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-platform-http</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-management</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-endpointdsl</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-spring</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>4.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
Edit 12/04/2022
Completely redid my classes with #ConfigurationProperties
So when I post to refresh the values in propertySource for AWS automatically update. So eg I change cobaltdlt to cobaltdlttest below, hit refresh, and then I can see the change when I query GET http://localhost:8080/actuator/env
So the refresh is working but it's not reflective in the #Component beans even though the propertySource is updating. In fact the only beans it is working with are the AWS beans.
Have you tried a PropertiesConfiguration bean? See here: https://www.baeldung.com/spring-reloading-properties.
Once configured correctly, it should automatically read changes to your properties file and reload them. Also, there are some limitations that are mentioned in that article that you should be aware of.
#I2obiN. As you have mentioned that ApplicationProperties is getting refreshed by Refresh Scopes, therefore actuator refresh is working properly.
But I noticed that you are using RefreshScope on main application class. IMO this actuator management/refresh will not restart application. You can try to create an extra method that reinitializes Camel Context.
Hope this helps!!
https://www.baeldung.com/java-restart-spring-boot-app#actuators-restart-endpoint
You can invoke the refresh Actuator endpoint by sending an empty HTTP POST to the client's refresh endpoint: http://localhost:8080/actuator/refresh . Then you can confirm it worked by visiting the http://localhost:8080/message endpoint.
And once you refresh, try to rebind immediately by calling the POST endpoint http://localhost:8080/actuator/env
This worked on a spring boot I tried and it reloads the values and you can see it in the stack trace.
I tried doing a field in spring data source with the given payload to Rebind and it reloads Example as the value.
Payload:
{"name":"spring.datasource.userName", "value":"Example"}
In the application.properties, add the following
management.endpoint.env.post.enabled=true
management.endpoint.restart.enabled=true
endpoints.sensitive=true
endpoints.actuator.enabled=true
management.security.enabled=false
management.endpoints.web.exposure.include=*
I'm new in Spring Boot, I'm trying to build a simple application with REST Api, and I'm getting this error immediately when starting the app:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-01-24 20:08:19.505 ERROR 11344 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
An attempt was made to call a method that does not exist. The attempt was made from the following location:
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration.requestMappingHandlerAdapter(WebMvcAutoConfiguration.java:369)
The following method did not exist:
'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration.requestMappingHandlerAdapter(org.springframework.web.accept.ContentNegotiationManager, org.springframework.format.support.FormattingConversionService, org.springframework.validation.Validator)'
The method's class, org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration, is available from the following locations:
jar:file:/C:/Users/user/.m2/repository/org/springframework/spring-webmvc/5.1.3.RELEASE/spring-webmvc-5.1.3.RELEASE.jar!/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class
The class hierarchy was loaded from the following locations:
org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration: file:/C:/Users/user/.m2/repository/org/springframework/spring-webmvc/5.1.3.RELEASE/spring-webmvc-5.1.3.RELEASE.jar
org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport: file:/C:/Users/user/.m2/repository/org/springframework/spring-webmvc/5.1.3.RELEASE/spring-webmvc-5.1.3.RELEASE.jar
Action:
Correct the classpath of your application so that it contains a single, compatible version of org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration
Process finished with exit code 0
I did not finish yet with the development of the app, but I can't go on because of this errors.
There are my classes so far:
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.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>micro1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>micro1</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</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<!-- <version>1.4.200</version>-->
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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>
<version>2.19.1</version>
</plugin>
</plugins>
</build>
</project>
controller:
package com.example.micro1.controllers;
import com.example.micro1.entities.User;
import com.example.micro1.services.Service;
import lombok.Data;
import org.springframework.web.bind.annotation.*;
#RestController
#RequestMapping("/users")
#Data
public class Controller {
private final Service service;
#PostMapping
User addNewUser(#RequestBody User user){
return service.add(user);
}
}
service:
package com.example.micro1.services;
import com.example.micro1.entities.User;
import com.example.micro1.repositories.Repository;
import lombok.Data;
#org.springframework.stereotype.Service
#Data
public class Service {
private final Repository repository;
public User add(User user){
return repository.save(user);
}
}
repository:
package com.example.micro1.repositories;
import com.example.micro1.entities.User;
import org.springframework.data.jpa.repository.JpaRepository;
#org.springframework.stereotype.Repository
public interface Repository extends JpaRepository<User, Integer> {
#Override
<S extends User> S save(S s);
}
One entity for now:
package com.example.micro1.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private String phoneNumber;
}
application.properties:
#h2
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
The application class:
package com.example.micro1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Micro1Application {
public static void main(String[] args) {
SpringApplication.run(Micro1Application.class, args);
}
}
Please tell me if there is something else that I should write here...
Thanks!
Your starter spring-boot-starter-web contains inside itself these dependencies
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.3</version>
<scope>compile</scope>
</dependency>
besides, you add in your pom.xml that:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
so, when you'll start your application you have in classpath ambiguity. I think it's cause of your problem.
Spring Boot starters save you the trouble of specifying explicitly declare dependency.
Try to remove spring-webmvc dependency.
I had this same issue when I run a Spring Boot Application of Web. But I got following error messages:
***************************
APPLICATION FAILED TO START
***************************
Description:
An attempt was made to call a method that does not exist. The attempt was made from the following location:
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration.configureHandlerExceptionResolvers(WebMvcAutoConfiguration.java:519)
The following method did not exist:
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration.addDefaultHandlerExceptionResolvers(Ljava/util/List;)V
The method's class, org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration, is available from the following locations:
jar:file:/Users/itzhouq/dev/mavne_repository/org/springframework/boot/spring-boot-autoconfigure/2.1.6.RELEASE/spring-boot-autoconfigure-2.1.6.RELEASE.jar!/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class
It was loaded from the following location:
file:/Users/itzhouq/dev/mavne_repository/org/springframework/boot/spring-boot-autoconfigure/2.1.6.RELEASE/spring-boot-autoconfigure-2.1.6.RELEASE.jar
Action:
Correct the classpath of your application so that it contains a single, compatible version of org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration
This may be spring-boot-autoconfigure's exception.So, I checked the dependency of this.
org.springframework.boot:spring-boot-web:2.2.1.RELEASE--> org.springframework.boot:spring-boot-starter:2.2.1.RELEASE -->
org.springframework.boot:spring-boot-autoconfigure:2.2.1.RELEASE(omitted for conflict with 2.1.6.RELEASE). Obviously, the autoconfigure was losing because of version conflict.For solve this problem, I added the following dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
confirm this dependency had be added in the module and reruned the application.
Add one more dependency is Spring-webMVC because spring web MVC is using for deploying your project
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.3</version>
<scope>compile</scope>
</dependency
I'm trying to integrate Hibernate Search in a Spring Boot 2 app. I have tried different versions following the compatibility list on their site but I always get this error when the app is started and "fullTextEntityManager.createIndexer().startAndWait();" is executed:
Exception in thread "main" java.lang.IllegalArgumentException: HSEARCH000349: Some of the specified entity types ('class java.lang.Object') are not indexed, nor is any of their subclasses.
After 3 days googling and trying lot of things I have no idea what else I can do.
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
...
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>${opencsv.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-orm</artifactId>
<version>5.10.6.Final</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-spatial</artifactId>
<version>5.5.5</version>
</dependency>
</dependencies>
As the datasource configuration is handled by spring boot I don't have a persistence.xml file so I put the Hibernate Search properties in application.properties. Actually I put these properties also in hibernate.properties trying to make this work.
application.properties
...
spring.datasource.username=*******
spring.datasource.password=*******
spring.jpa.database=MYSQL
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=false
spring.jpa.hibernate.naming.physicalstrategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.search.default.directory_provider=filesystem
spring.jpa.hibernate.search.default.indexBase=/lucene/indexes
hibernate.properties
hibernate.search.default.directory_provider=filesystem
hibernate.search.default.indexBase=/lucene/indexes
My entity Restaurant to be indexed:
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode
#Indexed
#Spatial
#Entity
#Table(name = "restaurant")
public class Restaurant {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Field(index = Index.YES, analyze = Analyze.NO, store = Store.YES)
private String name;
private String address;
#Latitude
private Double latitude;
#Longitude
private Double longitude;
}
I'm initializing Hibernate Search just after spring boot is started
#SpringBootApplication
public class PlacesApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context =
SpringApplication.run(PlacesApplication.class, args);
context.getBean(HibernateSearchService.class)
.initializeHibernateSearch();
}
And my Hibernate Search Service looks like:
#AllArgsConstructor
#Service
#Slf4j
public class HibernateSearchService {
private EntityManager entityManager;
#Transactional
public void initializeHibernateSearch() {
try {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
fullTextEntityManager.createIndexer().startAndWait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I found the issue, very very silly issue....
My IDE just imported the wrong Indexed annotation
It set import org.springframework.stereotype.Indexed; instead of import org.hibernate.search.annotations.Indexed;
UPDATE: I found some similar test in neo4j timetree source but using GraphAwareIntegrationTest, which extends ServerIntegrationTest. So I tried creating a GraphDatabaseService Bean for my test with the following, but still no luck. I get "There is no procedure with the name ga.timetree.events.attach registered for this database instance." Is this not possible?
#Bean
public GraphDatabaseService graphDatabaseService() {
GraphDatabaseService gds = new TestGraphDatabaseFactory().newImpermanentDatabaseBuilder().newGraphDatabase();
Procedures procedures = (Procedures)((GraphDatabaseFacade) gds).getDependencyResolver().resolveDependency(Procedures.class);
try {
ClassPathProcedureUtils.registerAllProceduresAndFunctions(procedures);
}catch (Exception ex) {
log.error("error", ex);
}
return gds;
}
=====================
Similar to this issue but I'm using Spring Boot 2, SDN5 with neo4j 3.2.5, graphaware and time tree. I have automatic event attachment setup, and i see events getting saved to the timetree, but I can't query using the procedure call using cypher. I get the error:
Caused by: org.neo4j.ogm.exception.CypherException: Error executing Cypher; Code: Neo.ClientError.Procedure.ProcedureNotFound; Description: There is no procedure with the name `ga.timetree.range` registered for this database instance. Please ensure you've spelled the procedure name correctly and that the procedure is properly deployed.
at org.neo4j.ogm.drivers.embedded.request.EmbeddedRequest.executeRequest(EmbeddedRequest.java:176)
I don't see a TimeTreeProcedures class as answered in the linked issue. Is this still supported in embedded/unit testing?
Also, if it is supported, I would like to use a CustomRootTimeTree. Any help or pointer to cypher that I can define the custom root tree id in the procedure call would also be very much appreciated. Thanks for any help!
Test:
#Test
public void testSingleTimeTree() {
User user = new User("alper#alper.com", "alper", "alper");
userRepository.save(user);
Collection<User> found = userRepository.findByEmail("alper#alper.com");
user = found.iterator().next();
Workout workout = new Workout(new DateTime().plusMonths(2).getMillis());
workoutRepository.save(workout);
GraphUnit.printGraph(graphDb);
Iterable<Workout> workouts = workoutRepository.findWorkouts();
for(Workout workout1 : workouts) {
log.info("workout: {}", workout1);
}
}
Repo (hard coded start/end for now):
public interface WorkoutRepository extends Neo4jRepository<Workout, Long> {
#Query("CALL ga.timetree.range({start: 1506826887000, end: 1512097287, create: false})")
Iterable<Workout> findWorkouts();
}
pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<spring-data-releasetrain.version>Kay-RELEASE</spring-data-releasetrain.version>
<!--<neo4j-ogm.version>3.0.0</neo4j-ogm.version>-->
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>${spring-data-releasetrain.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<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.neo4j</groupId>
<artifactId>neo4j-ogm-embedded-driver</artifactId>
<version>${neo4j-ogm.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>3.2.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- added by me -->
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-kernel</artifactId>
<version>3.2.5</version>
<type>test-jar</type>
</dependency>
<dependency>
<groupId>com.graphaware.neo4j</groupId>
<artifactId>graphaware-framework-embedded</artifactId>
<version>3.2.5.51</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.graphaware.neo4j</groupId>
<artifactId>timetree</artifactId>
<version>3.2.1.51.27</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-graphdb-api</artifactId>
<version>3.2.5</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-io</artifactId>
<version>3.2.5</version>
<type>test-jar</type>
</dependency>
<dependency>
<groupId>com.graphaware.neo4j</groupId>
<artifactId>tests</artifactId>
<version>3.2.5.51</version>
</dependency>
</dependencies>
I was able to finally get it working by debugging into the neo4j source. The tests that test and use Procedures are in https://github.com/graphaware/neo4j-timetree, and it's using ClassPathProcedureUtils class to load classes from target/classes directory. It looks for #Procedure annotations and will process those classes and the Procedures become available. Without modifying that to load classes from jars as well as target/classes, the only way I could get it to work (albeit a hack) is to copy the target/classes output from neo4j-timetree project into my project target/classes output dir.
UPDATE:
I was also able to get it working by just registering the procedures required directly using:
#Bean
public GraphDatabaseService graphDatabaseService() {
GraphDatabaseService gds = new TestGraphDatabaseFactory().newImpermanentDatabaseBuilder().newGraphDatabase();
try {
ClassPathProcedureUtils.registerAllProceduresAndFunctions(procedures);
Procedures procedures = ((GraphDatabaseFacade)gds).getDependencyResolver().resolveDependency(Procedures.class);
procedures.registerProcedure(TimedEventsProcedure.class);
procedures.registerProcedure(TimeTreeProcedure.class);
procedures.registerFunction(TimedEventsProcedure.class);
procedures.registerFunction(TimeTreeProcedure.class);
}catch (Exception ex) {
log.error("error", ex);
}
return gds;
}