#QuerydslPredicate throwing exception - java

I'm trying to understand how to use #QuerydslPredicate but my test API fails when it is called:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No primary or default constructor found for interface com.querydsl.core.types.Predicate] with root cause
java.lang.NoSuchMethodException: com.querydsl.core.types.Predicate.< init >()
This is the method in my Controller class:
#ResponseBody
#RequestMapping(value = "/user/query", method = RequestMethod.GET)
public Iterable<User> getByCriteria(#QuerydslPredicate(root = User.class) Predicate predicate)
{
return this.userDao.getByCriteria(predicate);
}
I've used this spring blog post and this example to try and implement my API but I don't understand what I am doing wrong.
Edit #1
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>email-encrypt</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
</parent>
<name>email-encrypt</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<querydsl.version>4.1.4</querydsl.version>
<springfox.version>2.6.1</springfox.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-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.59</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.59</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk15on</artifactId>
<version>1.59</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.14.1.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>${build.directory}/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Edit #2
I've create a sample project here.

If you comment out the #Configuration on the swagger configuration class it will work. I'm still trying to understand why, I guess that with that annotation the way spring loads the configuration is different and this is causing the issue.
//#Configuration
#EnableSwagger2
public class SwaggerConfiguration extends WebMvcConfigurationSupport

I think your problem lies in your pom.xml. Be sure you are using compatible version of query-dsl. For instance if you use spring-data-jpa 2.0.8, you should use querydsl-* 4.1.4+
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-*</artifactId>
<version>4.1.4</version>
</dependency>
you can check in maven repository which version you need
Edit 1 try to add the querydsl-core to your maven:
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-core</artifactId>
<version>4.1.4</version>
</dependency>

Extending on #cristobalrosa's answer, this might be due to web application not being configured by Spring Boot. For instance my project also had a SwaggerConfig extending WebMvcConfigurationSupport:
#Configuration
#EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {
// Docket bean
#Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
}
}
I removed the inheritance and manual resource handlers, and it works fine now.
Note: In addition to WebMvcConfigurationSupport, things like #EnableWebMvc & WebMvcConfigurer might also lead to Spring Boot's web autoconfiguration not being used.
Sources: Swagger Issue comment

Same error with me.
I just want to share the situation to may give some hints. So look at my config and dependencies and read articles that I linked. try #EnableWebMvc instead of 'WebMvcConfigurationSupport'
Error
java.lang.IllegalStateException: No primary or default constructor found for interface com.querydsl.core.types.Predicate
Caused by: java.lang.NoSuchMethodException: com.querydsl.core.types.Predicate.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3427)
at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2631)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:216)
dependencies
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation "org.springframework.data:spring-data-commons"
implementation "com.querydsl:querydsl-apt:4.3.1"
implementation "com.querydsl:querydsl-jpa:4.3.1"
}
Querydsl web support is available in spring-data-commons since 1.11
from https://www.baeldung.com/rest-api-search-querydsl-web-in-spring-data-jpa
Web Mvc Config
In my case, I have to implements WebMvcConfigurer and add #EnableWebMvc instead of WebMvcConfigurationSupport. I don't know why #EnableWebMvc is needed even I had extended WebMvcConfigurationSupport with #Configuration. I just guess WebMvcConfigurationSupport doesn't implements init() of Predicate.
#Configuration
//#EnableSpringDataWebSupport // <-- doesn't necessary for me
#EnableSwagger2
#EnableWebMvc // <-- add
public class SwaggerConfig implements WebMvcConfigurer { //<-- instead of 'WebMvcConfigurationSupport'
...
}
QueryDSL web support From Spring document
The feature will be automatically enabled along #EnableSpringDataWebSupport when Querydsl is found on the classpath.
https://docs.spring.io/spring-data/jpa/docs/1.9.0.RELEASE/reference/html/#core.web.type-safe
Controller
#GetMapping
public List<InputMethodDto.Response> getInputMethodTypeList(
#QuerydslPredicate(root = InputMethod.class) Predicate predicate) {
return service.getInputMethodList(predicate);
}
Repository
public interface InputMethodRepository extends JpaRepository<yourEntity, Long>, QuerydslPredicateExecutor<yourEntity>, QuerydslBinderCustomizer<QyourEntity> {
#Override
default void customize(final QuerydslBindings bindings, final QyourEntity root) {
bindings.bind(String.class).first((StringPath path, String value)-> path.eq(value));
}
}

Related

Spring Java - Parameter 0 of constructor

I'm trying to write a simple CRUD program and I get this error. The program is based after codecademy project. Not sure why I doesn't work.
If I comment out the constructor the error disappears.I don't have anything in my properties.
Can someone give me a hand?
Description:
Parameter 0 of constructor in com.example.FitApp3.controller.FoodController required a bean of type 'com.example.FitApp3.repository.FoodRepository' that could not be found.
Action:
Consider defining a bean of type 'com.example.FitApp3.repository.FoodRepository' in your configuration.
Process finished with exit code 1
This is my code:
Entity/Food.java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Food extends com.example.FitApp3.model.Entity {
private String foodName;
private int foodKcal;
private int foodProtein;
private int foodCarb;
private int foodFat;
public String getFoodName() {
return foodName;
}
public void setFoodName(String foodName) {
this.foodName = foodName;
}
public int getFoodKcal() {
return foodKcal;
}
public void setFoodKcal(int foodKcal) {
this.foodKcal = foodKcal;
}
public int getFoodProtein() {
return foodProtein;
}
public void setFoodProtein(int foodProtein) {
this.foodProtein = foodProtein;
}
public int getFoodCarb() {
return foodCarb;
}
public void setFoodCarb(int foodCarb) {
this.foodCarb = foodCarb;
}
public int getFoodFat() {
return foodFat;
}
public void setFoodFat(int foodFat) {
this.foodFat = foodFat;
}
}
Repository/FoodRepository.java
public interface FoodRepository extends CrudRepository<Food, Integer> {}
Controller/FoodController.java
#RestController
public class FoodController {
private FoodRepository foodRepository;
public FoodController(FoodRepository foodRepository) {
this.foodRepository = foodRepository;
}
}
Mainclass
#SpringBootApplication
public class FitApp3Application {
public static void main(String[] args) {
SpringApplication.run(FitApp3Application.class, args);
System.out.println("hello world");
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>FitApp3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>FitApp3</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>2.5.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Can you add #Repository annotation to FoodRepository interface.
#Repository
public interface FoodRepository extends CrudRepository<Food, Integer> {}
You need to replace spring-boot-starter-jdbc with spring-boot-starter-data-jpa as follows:
<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-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
You can have a look at the following links the difference between them, but basically, JPA helps you deal with your Database data by mapping it directly to Java objects:
https://www.baeldung.com/jpa-vs-jdbc
JPA or JDBC, how are they different?
I think you are just a little bit confused with spring-jdbc, spring-data and spring persistence interfaces abstraction, let me help. TL;DR solution is at the bottom:
In the constructor of FoodController you are declaring FoodRepository as a parameter, so spring have to find the bean of this time at runtime in order to create bean of FoodController. You have declared FoodRepository and extend it from CrudRepository. I guess, that you have done it with the assumption, that spring will create an implementation of FoodRepository at runtime (because it extends CrudRepository). But, unfortunately, it is not the spring-core module, that will create bean of FoodRepsitory, nor it is spring-jdbc. This interfaces are the part of spring-data project. So, for creation of the bean of the type FoodRepository is responsible current spring-data project in your classpath (I mean, it could be spring-data-jdbc, spring-data-jpa or whatever). This interfaces (CrudRepository, Repository e.t.c.) are common for all of the spring data projects, so they are shipped in spring-data-commons jar, this is why you have them available in classpath, because you have included spring-data-commons explicitly:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>2.5.1</version>
</dependency>
Another thing is that this starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
does not do anything with spring-data project - it just brings spring-jdbc, Hikari connection pool, and some other spring-boot stuff. In other words, the problem is that you do not have any spring-data project in your classpath, thats why FoodRepository bean is not created.
Also note: #Entity does not make sense here, becuase you do not have any jpa persistence provider in classpath
Solution:
To solve the problem, I suggest you to
Remove spring-data-commons dependency from pom.xml
Include spring-boot-starter-data-jpa into your project (into pom.xml). It will bring the appropriate version of spring-data-commons dependency.
Hope it helped, have a nice day!
Add #Repository annotation to FoodRepository interface
and also #Autowired annotation to the FoodRepository in FoodController.

Request validation doesn't happen in camel rest

I am trying to experiment by building some simple API's with apache camel. The request body for a post request is empty but camel doesn't return bad request instead it returns 201.
Here is what I do;
Generate classes from studentreg-api.yaml [This is a valid
openapi 3 yaml document]
Using camel, spring boot to build
REST endpoints Step
Configured camel rest endpoint with clientRequestValidation(true)
Start the server
Open /api-docs and validated if the mandatory attributes are marked
appropriately
From postman made request to the POST endpoint with blank request body
Expected: 400 - Bad request
Actual: 201
I couldn't figure out what is that I am missing.
BaseRouteConfig.java
#ComponentScan
#Configuration
public class BaseRouteConfig extends RouteBuilder {
#Autowired
private Environment environment;
#Value("${studentregistration.api.path}")
private String basePath;
#Bean
ServletRegistrationBean servletRegistrationBean() {
ServletRegistrationBean servlet = new ServletRegistrationBean(new CamelHttpTransportServlet(), basePath + "/*");
servlet.setName("CamelServlet");
return servlet;
}
#Override
public void configure() throws Exception {
restConfiguration().component("servlet")
.bindingMode(RestBindingMode.json)
.dataFormatProperty("pretty-print", "true")
.enableCORS(true)
.port(environment.getProperty("server.port", "8085"))
.contextPath(basePath)
.apiContextPath("/api-docs")
.apiVendorExtension(true)
.apiProperty("api.title", "Student registration")
.apiProperty("api.version", "0.1")
.apiProperty("cors", "true")
.clientRequestValidation(true);
}
}
RegisterStudentRoute.java
#Component
public class RegisterStudentRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
rest("/api/").consumes(MediaType.APPLICATION_JSON_VALUE)
.produces(MediaType.APPLICATION_JSON_VALUE)
.post("/registration")
.type(RegisterStudentRequest.class)
.clientRequestValidation(true)
.outType(RegisterStudentResponse.class)
.responseMessage().code(HttpStatus.CREATED.value())
.endResponseMessage()
.route().routeId("create-student-registration")
.setHeader(Exchange.HTTP_RESPONSE_CODE, simple("201"))
.to("log:success")
.end().endRest();
}
}
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.5.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>camel-rest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>camel-rest</name>
<description>Demo project for Spring Boot & camel rest</description>
<properties>
<java.version>16</java.version>
<camel.version>3.10.0</camel.version>
<openapi-generator.version>5.1.0</openapi-generator.version>
<springfox.version>2.9.2</springfox.version>
<jackson-databind.version>0.2.1</jackson-databind.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.apache.camel.springboot</groupId>
<artifactId>camel-servlet-starter</artifactId>
<version>3.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jackson-starter</artifactId>
<version>3.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-openapi-java-starter</artifactId>
<version>3.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>3.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-http-starter</artifactId>
<version>3.9.0</version>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator</artifactId>
<version>${openapi-generator.version}</version>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>${jackson-databind.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.4.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>5.1.0</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/api.yaml</inputSpec>
<generatorName>spring</generatorName>
<apiPackage>com.sample.camel-rest.api</apiPackage>
<modelPackage>com.sample.camel-rest.model</modelPackage>
<supportingFilesToGenerate>
ApiUtil.java
</supportingFilesToGenerate>
<configOptions>
<delegatePattern>true</delegatePattern>
<outputDir>${project.basedir}/generated</outputDir>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
ok! I have figured out a simpler way to handle validation. Adding a route to bean-validator solved the problem! If we need to build custom error messages or if you need to build error model based on failures, you can use camel processor and javax.validator.
RegisterStudentRoute.java
#Component
public class RegisterStudentRoute extends RouteBuilder {
#Autowired
RegisterStudentRequestValidator registerStudentRequestValidator;
#Override
public void configure() throws Exception {
rest("/api/").consumes(MediaType.APPLICATION_JSON_VALUE)
.produces(MediaType.APPLICATION_JSON_VALUE)
.post("/registration")
.type(RegisterStudentRequest.class)
.clientRequestValidation(true)
.param().name("request-id").dataType("string")
.type(RestParamType.header).required(true)
.endParam()
.outType(RegisterStudentResponse.class)
.responseMessage().code(HttpStatus.CREATED.value())
.endResponseMessage()
.route().routeId("create-student-registration")
// .process(registerStudentRequestValidator)
.to("direct:validateReq")
.setHeader(Exchange.HTTP_RESPONSE_CODE, simple("201"))
.to("log:success")
.end().endRest();
from("direct:validateReq")
.to("bean-validator://x")
.to("mock:end");
}

Injection fails on components to deployed Tomcat server [Spring Boot]

When I try to deploy my .war project (Spring Boot) on a Tomcat server I get the following exception on the logs. Note that this exception doesn't happen locally, so I can only reproduce it on server enviroment.
Complete stacktrace https://pastebin.com/8uFqwk0U
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mappingComponent': Failed to introspect bean class [com.project.components.MappingComponent] for lookup method metadata: could not find class that it depends on; nested exception is java.lang.NoClassDefFoundError: java/time/temporal/Temporal
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:269) ~[spring-beans-4.3.5.RELEASE.jar:4.3.5.RELEASE]
I searched of course about this issue and I've changed some dependencies on ton pom.xml, also removed and added constructors just in case but I couldn't figure out why this is happening.
MappingComponent the calss that exception happens
#Component
public class MappingComponent {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
#Autowired
Repository1 repo1;
#Autowired
Repository2 repo2;
//no constructors
//methods that are using the repositories
}
MappingController the class that injects MappingComponent
#RestController
#CrossOrigin
#RequestMapping("/services")
public class MappingController {
#Autowired
private ClientComponent clientComponent;
#Autowired
private MappingComponent mappingComponent;
//no constructors
//services that are using the components
}
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 http://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.4.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>services</groupId>
<artifactId>services</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>services</name>
<description>Services</description>
<packaging>war</packaging>
<properties>
<java.version>1.7</java.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-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</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-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Main class
#SpringBootApplication
public class ServicesApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ServicesApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(ServicesApplication.class, args);
}
}
I am aware that both java and spring are outdated, but it doesn't depend on me to upgrade them to a newer version. And that's not the issue because there are other services deployed with the same version (and identical pom.xml).
Temporal class has been introduced only in 1.8 and in your pom I see that you use 1.7.
When you are not sure of when a class has been introduced, just check in the Javadoc the #Since tag.
You might need to external the external dependency jar into the lib directory of the Tomcat web server. First shutdown tomcat, add jar to the lib directory, and then startup tomcat.

How to fix Error creating bean with name 'requestMappingHandlerMapping'

I'm creating a web application using spring-boot with annotation based configuration.
At first, I created a spring application with annotation based config using Hibernate and JPA. It was working fine but then I needed to add spring-boot to my application and now cannot start it. Here is the code:
#SpringBootApplication
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class Runner {
public static void main(String[] args) {
SpringApplication.run(Runner.class, args);
}
}
#Configuration
#EnableTransactionManagement
#ComponentScans(value = { #ComponentScan("com.alex.pharm.dao"),
#ComponentScan("com.alex.pharm.service") })
public class AppConfig {
#Bean
public LocalEntityManagerFactoryBean geEntityManagerFactoryBean() {
LocalEntityManagerFactoryBean factoryBean = new LocalEntityManagerFactoryBean();
factoryBean.setPersistenceUnitName("LOCAL_PERSISTENCE");
return factoryBean;
}
#Bean
#ConditionalOnMissingBean(type = "JpaTransactionManager")
public JpaTransactionManager geJpaTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(geEntityManagerFactoryBean().getObject());
return transactionManager;
}
}
#RestController
public class HelloController {
#RequestMapping("/")
public String index() {
return "Greetings from Spring Boot!";
}
}
<groupId>com.sachatol.pharmacy</groupId>
<artifactId>pharmacyWebStore</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency><!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<!-- Hibernate 5.2.9 Final -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.9.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!-- Spring ORM -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
But when I try to run it I get the following exception:
ConfigServletWebServerApplicationContext : Exception encountered during context initialization
- cancelling refresh attempt:org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'requestMappingHandlerMapping'
defined in class path resource
[org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]:
Initialization of bean failed; nested exception is java.lang.NoSuchMethodError:
org.springframework.web.servlet.handler.AbstractHandlerMapping.obtainApplicationContext()
Lorg/springframework/context/ApplicationContext;
How can I fix it?
Issue found - I used the old version for spring-context in pom (4.3.7.RELEASE) which override the one that spring-boot has and was the reason of NoSuchMethodError. So spring-context dependency was old and obsolete after removing or changing it to newer version (5.0.3) application started fine
Your #RequestMapping seems missing some parts, try with something like that:
#RequestMapping(value = "/", method = RequestMethod.GET)
This also happens if you have two methods with same request mapping values. Make sure you have unique RequestMapping values.
In your request mapping, you have incorrectly used :
#RequestMapping("/")
Instead, use this mapping to specify the end-point and the request-method like this :
#RequestMapping(value = "/", method = RequestMethod.GET)
Hope it will solve your problem.

how to set-up in memory database for IntegrationTest using springboot and liquibase

Using liquibase and springboot , created db changelogs and able to run it successfully with maven-liquibase-plugin (mvn liquibase:update). I'm writing integration tests , in which liquibase changes needs to be created programmatically .
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = DummyApplication.class)
#ActiveProfiles("test")
public class TestDummyService
{
#Autowired
private SpringLiquibase springLiquibase;
...
#Test
public void testDummyRequest()
{
try {
Connection connection = springLiquibase.getDataSource().getConnection();
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
Liquibase liquibase = new liquibase.Liquibase("liquibase/changelog/db-changelog-master.xml", new ClassLoaderResourceAccessor(), database);
liquibase.update(new Contexts(springLiquibase.getContexts()), new LabelExpression(springLiquibase.getLabels()));
} catch (LiquibaseException | SQLException e) {
e.printStackTrace();
}
}
Getting the below exception while running the above test.
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125)
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'liquibase' defined in class path resource [org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]:
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [liquibase.integration.spring.SpringLiquibase]:
Factory method 'liquibase' threw exception; nested exception is java.lang.NoSuchMethodError: liquibase.integration.spring.SpringLiquibase.setLiquibaseSchema(Ljava/lang/String;)V
Caused by: java.lang.NoSuchMethodError: liquibase.integration.spring.SpringLiquibase.setLiquibaseSchema(Ljava/lang/String;)
below is application-test.property file .
#NOTE : spring.liquibase is the working one .
liquibase.changeLog=classpath:liquibase/changelog/db-changelog-master.xml
liquibase.enabled=true
liquibase.url=jdbc:h2:mem:cpass;DB_CLOSE_DELAY=-1
liquibase.user=root
liquibase.password=
spring.liquibase.dropFirst=true
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
jdbc.driverClassName=org.h2.Driver
spring.liquibase.enabled=true
spring.liquibase.change-log=classpath:liquibase/changelog/db-changelog-master.xml
#spring.liquibase.driver=com.mysql.jdbc.Driver
spring.liquibase.url=jdbc:mysql://localhost:3306/dummy
spring.liquibase.user=root
spring.liquibase.password=
**pom.xml : **
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.3.RELEASE</version>
<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-tomcat</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.1.3.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.4.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.3.RELEASE</version>
</plugin>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<propertyFile>liquibase/liquibase.properties</propertyFile>
<changeLogFile>liquibase/changelog/db-changelog-master.xml</changeLogFile>
</configuration>
</plugin>
</plugins>
</build>
Is there anything Im missing in the test class or any sample project url is also much helpful . Im new to springboot and liquibase .
Spring Boot 2.1.3 depends on Liquibase 3.6.3, but you have specified 3.4.2 in your pom.xml.
Having said that, Spring Boot's Liquibase autoconfiguration will do everything you've written yourself in your unit test because you've already created the properties to activate the autoconfiguration. You could delete all of the code in the test method and just #Autowire a DataSource into the test class instead. Spring will apply the Liquibase changelog for you.
One last thing: if you can, it would be better to add a <parent> to your pom.xml which means you won't need to specify the individual versions of each dependency (including Liquibase). Spring Boot has a lot of dependencies and it's a lot of work keeping the versions in sync when you upgrade. This would also have prevented your NoSuchMethodError.

Categories