Spring properties Validation in nested ConfigurationProperties - java

I'm using #ConfigurationProperties to keep track of my properties. Everything work fine, including class member for sub-configuration. Properties are well loaded and the framework uses the getter to determine the "name of the context". However I have trouble when trying validation, it does not validate sub properties.
<?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>
<groupId>be.test</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.1.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.properties:
test.value = 4
test.value2 = 6
test.sub.subValue = 9
ValidationApplication.java
#SpringBootApplication
public class ValidationApplication implements CommandLineRunner
{
private final TestProperties properties;
public ValidationApplication(TestProperties properties) {
this.properties = properties;
}
#Override
public void run(String... args) {
System.out.println("=========================================");
System.out.println("Value: " + this.properties.getValue());
System.out.println("Value2: " + this.properties.getValue2());
System.out.println("SubValue: " + this.properties.getSub().getSubValue());
System.out.println("=========================================");
}
public static void main(String[] args) throws Exception {
new SpringApplicationBuilder(ValidationApplication.class).run(args);
}
}
Main ConfigurationProperties, TestProperties.java
#Component
#ConfigurationProperties(prefix = "test")
public class TestProperties
{
#Min(4)
private int value;
#Max(6)
private int value2;
private SubProperties sub;
... getters and setters ...
}
Sub ConfigurationProperties, SubProperties.java
#Component
#ConfigurationProperties
public class SubProperties
{
#Max(10)
private int subValue;
... getter & setter ...
}
So the output with the given properties file:
=========================================
Value: 4
Value2: 6
SubValue: 9
=========================================
If I go out of range with Value and Value2, all is fine (validation works):
***************************
APPLICATION FAILED TO START
***************************
Description:
Binding to target be.test.TestProperties#6cb6decd failed:
Property: test.value2
Value: 7
Reason: must be less than or equal to 6
Property: test.value
Value: 2
Reason: must be greater than or equal to 4
Action:
Update your application's configuration
With these values however:
test.value = 4
test.value2 = 6
test.sub.subValue = 11
The validation does not trigger (even if there is a #Max constraint on sub property).
Is it normal?
What did I miss?

You missed a #Valid annotation:
#Component
#ConfigurationProperties(prefix = "test")
public class TestProperties
{
#Min(4)
private int value;
#Max(6)
private int value2;
#Valid
private SubProperties sub;
... getters and setters ...
}

Related

Simple Spring Data Couchbase Find Query Not Working

I'm new to Couchbase and Spring Data Couchbase and am having issues getting a simple find query to work. I am running the community edition of couchbase (version 6.6.0), have the latest version of Spring Data Couchbase, and have created a small spring boot app to query from a new bucket I created. I am able to connect to the database ok, but none of the find queries I am using return any data. I have gone into the bucket and added a few indexes, but that didn't seem to help either. I am hoping it is just something small that I am missing.
Here is my code...
Config
#Configuration
#EnableCouchbaseRepositories
public class Config extends AbstractCouchbaseConfiguration {
#Override
public String getConnectionString() {
return "couchbase://127.0.0.1";
}
#Override
public String getUserName() {
return "Administrator";
}
#Override
public String getPassword() {
return "admin1";
}
#Override
public String getBucketName() {
return "testing";
}
#Override
protected boolean autoIndexCreation() {
return true;
}
}
Model
#Document
public class UserInfo {
#Id
private String id;
#QueryIndexed
private String name;
public String getId() {
return id;
}
public String getName() {
return name;
}
}
Repository
#Repository
public interface UserRepository extends CrudRepository<UserInfo, String> {
List<UserInfo> findByName(String name);
}
Main code that runs on app startup. I never seem to be getting data back, even though I have a few documents in my bucket.
#Configuration
public class StartupConfig {
#Autowired
public TravelRepository travelRepository;
#Autowired
public UserRepository userRepository;
#PostConstruct
public void postConstruct() {
System.out.println("Processing data...");
List<UserInfo> userInfo = userRepository.findByName("Steve");
//List<NameInfo> nameInfo = nameRepository.findAll();
if (userInfo.size() == 0) {
System.out.println("No data found");
} else {
System.out.println("Data found: " + userInfo.get(0).getName());
}
}
}
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.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>couchbase</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>couchbase</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-data-couchbase</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
OK, I figured out the issue. I was manually inserting data via the Admin console, and I didn't realize that you have to add an _class attribute to your documents. When Spring Data Couchbase generates its queries, they will look something like this:
Select * from testing where name = "Steve" and _class= "com.example.couchbase.model.UserInfo";
And it won't find any data if the _class attribute is missing (unless there is some property setting or something that lets you get around this).

#MicronautTest - limit what is instantiated

Whenever I used #MicronautTest in my project, the whole application is started as a whole and because certain things need to be done at startup by services, they are executed also.
I don't need the whole Singleton shebang when I'm testing a simple controller.
My question is how do I limit which controllers and singletons are loaded when testing Micronaut?
I have a small demo example which shows the problem
Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>micronaut-test</artifactId>
<version>0.1</version>
<packaging>${packaging}</packaging>
<parent>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-parent</artifactId>
<version>2.5.1</version>
</parent>
<properties>
<packaging>jar</packaging>
<jdk.version>11</jdk.version>
<release.version>11</release.version>
<micronaut.version>2.5.1</micronaut.version>
<exec.mainClass>com.example.Application</exec.mainClass>
<micronaut.runtime>netty</micronaut.runtime>
</properties>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-validation</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-runtime</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.micronaut.build</groupId>
<artifactId>micronaut-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Uncomment to enable incremental compilation -->
<!-- <useIncrementalCompilation>false</useIncrementalCompilation> -->
<annotationProcessorPaths combine.children="append">
</annotationProcessorPaths>
<compilerArgs>
<arg>-Amicronaut.processing.group=com.example</arg>
<arg>-Amicronaut.processing.module=micronaut-test</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.java
package com.example;
import io.micronaut.runtime.Micronaut;
public class Application {
public static void main(String[] args) {
Micronaut.run(Application.class, args);
}
}
A simple service that throws whenever it is instantiated to indicate the problem
#Singleton
public class SingletonService {
#EventListener
public void init(ApplicationStartupEvent event) {
throw new RuntimeException("I was initialized");
}
}
A simple controller
#Controller
public class TestController {
#Get
public Simple findAll() {
return new Simple("ATest");
}
public static class Simple {
private final String test;
public Simple(String test) {
this.test = test;
}
public String getTest() {
return test;
}
}
}
And a straightforward test
#MicronautTest
class TestControllerTest {
#Inject
#Client("/")
RxHttpClient rxHttpClient;
#Test
void controller() {
HttpResponse<ByteBuffer> byteBufferHttpResponse = rxHttpClient.exchange("/").blockingFirst();
assert byteBufferHttpResponse.getStatus().getCode() == 200;
}
}
The test results are
[INFO] Running com.example.controller.TestControllerTest
11:01:52.804 [main] INFO i.m.context.env.DefaultEnvironment - Established active environments: [test]
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 7.232 s <<< FAILURE! - in com.example.controller.TestControllerTest
[ERROR] com.example.controller.TestControllerTest Time elapsed: 7.229 s <<< ERROR!
java.lang.RuntimeException: I was initialized
How do I prevent the test from starting that SingletonService? Stubbing is an option but keep in mind that this is a simple demo illustrating the issue for a bigger project. Is there no other straightforward way?
According to the docs of #MicronautTest, it shouldn't be scanning the classpath but it clearly is?
Here are some other configurations I've already attempted without any success:
Adding a ApplicationBuilder that disables eagerInit
#MicronautTest(application = TestControllerTest.TestApplication.class)
class TestControllerTest {
public static class TestApplication {
public static void main(String[] args) {
Micronaut.build(args)
.eagerInitAnnotated(null)
.eagerInitSingletons(false)
.mainClass(TestApplication.class);
}
}
#Inject
#Client("/")
RxHttpClient rxHttpClient;
#Test
void controller() {
HttpResponse<ByteBuffer> byteBufferHttpResponse = rxHttpClient.exchange("/").blockingFirst();
assert byteBufferHttpResponse.getStatus().getCode() == 200;
}
}
Passing along a contextbuilder
#MicronautTest(contextBuilder = TestControllerTest.TestContextBuilder.class)
class TestControllerTest {
public static class TestContextBuilder extends DefaultApplicationContextBuilder {
public TestContextBuilder() {
eagerInitSingletons(false);
eagerInitAnnotated(null);
eagerInitConfiguration(false);
}
}
#Inject
#Client("/")
RxHttpClient rxHttpClient;
#Test
void controller() {
HttpResponse<ByteBuffer> byteBufferHttpResponse = rxHttpClient.exchange("/").blockingFirst();
assert byteBufferHttpResponse.getStatus().getCode() == 200;
}
}
Which all yield the same response.
Hopefully someone knows how to limit the scope of bean instantation with the #MicronautTest or I'll most likely switch back to Spring boot
Thanks in advance
My question is how do I limit which controllers and singletons are
loaded when testing Micronaut?
At least there is the #Requires annotation that allows doing flexible configuration if a bean should be loaded within the current environment.
For example, in your case it should be something like:
import javax.inject.Singleton;
import io.micronaut.context.annotation.Requires;
#Singleton
#Requires(notEnv = {Environment.TEST})
public class SingletonService {
#EventListener
public void init(ApplicationStartupEvent event) {
throw new RuntimeException("I was initialized");
}
}
As a result, the exception from the service is not thrown.
However, I don't really know the purpose why you need to exclude the service. And it could be that other approaches might be more convenient.
For example, see Mocking Collaborators section from the micronaut test documentation: https://micronaut-projects.github.io/micronaut-test/latest/guide/

Unable to find solution to Parameter 0 of constructor in required a bean of type 'org.springframework.jdbc.core.NamedParameterJdbcTemplate'

I'm very new to Springboot and I've searched for the solution to be able to fix the error but with no avail.
I still keep getting this error:
```
Description:
Parameter 0 of constructor in sample.ArticlesRepository required a bean of type 'org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate' in your configuration.
Here is my 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.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>sprinboot_project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Sprinboot_Project</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>8</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</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-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.3.0.RELEASE</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
Here is my ArticlesRepository:
Here is my ArticlesRepository:
#Repository
public class ArticlesRepository implements ArticledDao{
public ArticlesRepository(NamedParameterJdbcTemplate template) {
this.template = template;
}
NamedParameterJdbcTemplate template;
#Override
public List<Articles> findAll() {
return template.query("select * from article", new ArticlesRowMapper());
}
#Override
public void deleteArticles(Articles articles) {
final String sql = "delete from article where articleid=:articleid";
Map<String,Object> map=new HashMap<String,Object>();
map.put("articleid", articles.getId());
template.execute(sql,map,new PreparedStatementCallback<Object>() {
#Override
public Object doInPreparedStatement(PreparedStatement ps)
throws SQLException, DataAccessException {
return ps.executeUpdate();
}
});
}
}
Article Dao class:
package sample;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface ArticledDao {
List<Articles> findAll();
public void deleteArticles(Articles articles);
}
Here is my Main class:
package sample;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#SpringBootApplication(scanBasePackages="sample")
#EnableJpaRepositories("sample")
public class Main {
public static void main(String[] args) throws Exception {
SpringApplication.run(Main.class, args);
}
}
application.properties:
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.show-sql=true
spring.datasource.url=jdbc:postgresql://localhost:5432/articles
spring.datasource.username=*******
spring.datasource.password=*******
spring.datasource.initialization-mode=always
spring.datasource.initialize=true
spring.datasource.continue-on-error=true
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
I hope you can provide a solution that I've couldn't find in stackoverflow and I will be grateful for the help.
Github link: https://github.com/Editux/springboot/tree/main/sprinboot_project
The tutorial I was following : https://dzone.com/articles/bounty-spring-boot-and-postgresql-database
List of files:
Your class ArticlesRepository has a field NamedParameterJdbcTemplate Spring want to set dependency with type NamedParameterJdbcTemplate for correctly creating ArticlesRepository but he can't find any bean with type NamedParameterJdbcTemplate.
You should declare one or more beans with type NamedParameterJdbcTemplate in your Spring context by using any of the possible annotations #Component or #Bean in the configuration class.
DAO object should be an entity, not repository
also, in your repository class, you don't have to implement the default methods like findAll and delete...I'd completely rework your code to this:
Entity class
#Entity
#Table(name = "articles")
public class ArticleDAO {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private boolean active;
// getters and setters (or use Lombok)
}
Repository class
#Repository
public interface ArticleRepository extends CrudRepository<ArticleDAO, Integer> {
}
Apperantly I needed to remove this spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration from application.properties to fix the error.

Problem with spring boot annotation autowired

I have the following problem. I trying to start a Spring Boot application with the DB2 database with Hybernate. So i created a repository and used the #Autowired annotation to get some data from the DB. The problem is that when I run the application i receive the following error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field studenteRepository in com.ibm.snam.ai4legal.controller.HelloWorldController required a bean of type 'com.ibm.snam.ai4legal.repositories.StudenteRepository' that could not be found.
Action:
Consider defining a bean of type 'com.ibm.snam.ai4legal.repositories.StudenteRepository' in your configuration.
Here are the classes of the application
Application class:
package com.ibm.snam.ai4legal.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication(scanBasePackages = {"com.ibm"})
public class SBApplication {
public static void main(String[] args) {
SpringApplication.run(SBApplication.class, args);
}
}
Repository class:
package com.ibm.snam.ai4legal.repositories;
import org.springframework.data.repository.CrudRepository;
import com.ibm.snam.ai4legal.model.Studente;
public interface StudenteRepository extends CrudRepository<Studente, Integer>{
}
Model class:
package com.ibm.snam.ai4legal.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class Studente{
#Id
#GeneratedValue
private int id;
private String nome;
private String cognome;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getnome() {
return nome;
}
public void setnome(String nome) {
this.nome = nome;
}
public String getcognome() {
return cognome;
}
public void setcognome(String cognome) {
this.cognome = cognome;
}
}
Controller class:
package com.ibm.snam.ai4legal.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import com.ibm.snam.ai4legal.repositories.StudenteRepository;
#RestController
public class HelloWorldController {
#Autowired
StudenteRepository studenteRepository;
#GetMapping(value = "/home")
public ModelAndView helloworld() {
ModelAndView hello = new ModelAndView("helloworld");
return hello;
}
}
and here the pom.xml file
<?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>
<groupId>projects</groupId>
<artifactId>springwebapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</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>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.ibm.db2.jcc</groupId>
<artifactId>db2jcc4</artifactId>
<version>4.26.14</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
<!-- <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>-->
<repositories>
<repository>
<id>repo</id>
<url>file://${project.basedir}/lib</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<packaging>war</packaging>
</project>
On the internet I found that I should insert <context:annotation-config/> in some configuration file but I have no idea in which file I have to put it. Someone can help?
You have to use #ComponentScan annotation. Try the below code.
#ComponentScan({"com.ibm.*"})
#SpringBootApplication
public class SBApplication {
public static void main(String[] args) {
SpringApplication.run(SBApplication.class, args);
}
}
Also mention #Repository annotation in StudenteRepository class.
Either move SBApplication to com.ibm.snam.ai4legal package so it can benefit from default component scanning or add the following annotations to specify packages to be scanned for entities and repositories.
#SpringBootApplication(scanBasePackages = {"com.ibm"})
#EnableJpaRepositories(basePackages = {"com.ibm"})
#EntityScan(basePackages = {"com.ibm"})
public class SBApplication {
public static void main(String[] args) {
SpringApplication.run(SBApplication.class, args);
}
}
Since you are using spring-boot-starter-data-jpa you need to provide the annotation #EnableJpaRepositories to tell springboot to autoconfigure everything.So you might want to use the auto configuration feature of springboot.The #EnableJpaRepositories annotation is not mandatory for auto configuring the spring-data-jpa but in some cases if spring component scan didn't recognize spring-data-jpa in classpath you will have to use this annotation to tell spring to autoconfigure it.
#EnableJpaRepositories will enabling auto configuration support for Spring Data JPA required to know the path of the JPA the repositories. By default, it will scan only the main application package and its sub packages for detecting the JPA repositories.So take care to put the main application class at the root package of your application.
#EnableJpaRepositories(basePackages ="com.ibm")
#SpringBootApplication(scanBasePackages = {"com.ibm"})
public class SBApplication {
public static void main(String[] args) {
SpringApplication.run(SBApplication.class, args);
}
}
Also, if your entity classes are not in the same package then you can use the #EntityScan annotation to specify the base packages. In your case you have not specifies the #Repository annotation on your interface which will tell spring-boot to create default implementations for your interface.If that annotation is not provided then spring will just ignore the interface and the bean creation will not happen.You won't be able to autowire it .So provide that and have methods declared in your interface and spring-bot will take care of the rest.
#Repository
public interface StudenteRepository extends CrudRepository<Studente, Integer>{
//If to find a student record by the id attribute
public Studente findById();
}

Maven cannot resolve classes

I have a curious problem with maven during test and deploy.
Project structure
src/main/java/com/../models/Employee.java
src/test/java/com/../models/EmployeeTest.java
Employee
public class Employee {
private final String name;
private final Dollars salary;
public Employee(String name, Dollars salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public Dollars getSalary() {
return this.salary;
}
}
Dollars
public class Dollars {
private final BigDecimal value;
public Dollars(BigDecimal value) {
this.value = value;
}
public BigDecimal getValue() {
return value;
}
}
EmployeeTest
public class EmployeeTest {
#Test
public void justASimpleTest() {
Employee employee = new Employee("David", new Dollars(BigDecimal.valueOf(100)));
Employee updatedEmployee = updateSalary(BigDecimal.valueOf(200)).apply(employee);
assertEquals(BigDecimal.valueOf(200), updatedEmployee.getSalary().getValue());
}
private Function<Employee, Employee> updateSalary(final BigDecimal value) {
return employee -> new Employee(employee.getName(), new Dollars(value));
}
}
The problem
When i run "test", "verify" or "install" i get the following error:
cannot find symbol: class Employee
ONLY IN THE FUNCTION!
private Function<Employee, Employee> updateSalary(final BigDecimal value) {...}
^^^^^^^^ ^^^^^^^^
But intelliJ can resolve references indeed i've no errors provided by IntelliJ, furthermore build via maven and test using JUnit run in IntelliJ works!
After some attempts i've noted that this problem appears when packaging is set to jar, with <packaging>pom</packaging> all works fine.
This problem persiste though via cmd using "mvn clean install", via maven inside IntelliJ and on CI/CD(teamcity)
POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<groupId>XXX</groupId>
<artifactId>YYY</artifactId>
<version>ZZZ</version>
<artifactId>sample</artifactId>
<properties>
<junit.version>4.11</junit.version>
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<proc>only</proc>
<generatedSourcesDirectory>${project.build.directory}/generated-sources/annotations
</generatedSourcesDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.7</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
Can someone explain me why this happens?
Thanks :)
I found the problem!
Using <packaging>pom</packaging> tests are skipped this is why it works but this is not the solution!
The problem is that i'm using <proc>only</proc>. This property when has 'only' value means that only annotation processes will be executed, no compilation. This explain why in install phase it cannot find Employee class.
Further details about proc configuration HERE

Categories