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
Related
I have two different aspects in my Selenium test automation project and I am using load time weaving with AspectJ. Both aspects run fine when running under test methods in that class.
The case where AspectA running on #Before("#annotation(ChangeToIFrameA)") on a method1 that is under a method0 that is already annotated with #Before class it overrides the second aspect call AspectB on method2 that is called under method1.
Aspect A class
package com.stackoverfow.FrameHandling;
#Aspect
public class AspectA {
#Before("#annotation(com.stackoverfow.FrameHandling.ChangeToIFrameA)")
public void switchIFrameA(WebDriver driver)) {
driver.switchTo().frame("IFrameA name");
}
}
Custom Annotated class for Aspect A to run
package com.stackoverfow.FrameHandling;
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface ChangeToIFrameA {
}
Aspect B class
package com.stackoverfow.FrameHandling;
#Aspect
public class AspectB {
#Before("execution(com.stackoverfow.NavigationBar.*(..))")
public void switchIFrameB(WebDriver driver)) {
driver.switchTo().frame("IFrameB name");
}
#After("execution(com.stackoverfow.NavigationBar.*(..))")
public void switchIFrameA(WebDriver driver)) {
driver.switchTo().frame("IFrameA name");
}
}
Navigation Bar Class
package com.stackoverfow.Navigation;
class NavigationBar{
class NavigationBar(){}
public void goToHomePage(){
//Navigates to Home Page
}
public void goToHelpPage(){
//Navigates to Help Page
}
public void goToUserAccount(){
//Navigates to User Account Page
}
}
Test Class that uses TestNG
package com.stackoverfow.NavigationTests;
public class AppBasicTests {
#BeforeClass(alwaysRun = true)
public void login(ITestContext context) {
//logs into the application
takeCareOfNavigationToHomePage();
}
#BeforeMethod(alwaysRun = true)
public void openSecondTab(ITestContext context) {
//Open a new tab
}
#AfterMethod(alwaysRun = true)
public void closeSecondTab() {
//closes the secondary tab
}
#AfterClass(alwaysRun = true)
public void logout() {
//logs out from the app
}
//Annotated to private method that is called inside login() method which is annotated by #Before class
#ChangeToIFrameA
private void takeCareOfNavigationToHomePage(){
NavigationBar navigationBar = new NavigationBar();
navigationBar.goToHomePage();// Assuming AspectB runs before and after this method call for switching frames
}
//Assuming it switches to FrameA before running the test
#ChangeToIFrameA
#Test(enabled = true)
public void testNavigation(){
NavigationBar navigationBar = new NavigationBar();
navigationBar.goToHelpPage();// Assuming AspectB runs
before and after this method call for switching frames
}
}
aop.xml
<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
<aspects>
<aspect name="com.stackoverfow.FrameHandling.AspectA"/>
</aspects>
<aspects>
<aspect name="com.stackoverfow.FrameHandling.AspectB"/>
</aspects>
</aspectj>
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>
<groupId>com.stackoverflow</groupId>
<artifactId>UiTestAutomation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>UiTestAutomation</name>
<properties>
<!-- Maven Plugins -->
<maven-compiler-version>3.6.0</maven-compiler-version>
<maven-surefire-version>2.22.2</maven-surefire-version>
<selenium-version>3.14.0</selenium-version>
<testng-version>7.4.0</testng-version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<useIncrementalCompilation>${useIncrementalCompilation} </useIncrementalCompilation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-version}</version>
<configuration>
<argLine>-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/1.9.8/aspectjweaver-1.9.8.jar"</argLine>
</configuration>
<executions>
<execution>
<phase>process-sources</phase>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.8</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.22.2</version>
</plugin>
</plugins>
</build>
<dependencyManagement>
</dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium-version}</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-firefox-driver</artifactId>
<version>${selenium-version}</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-htmlunit-driver</artifactId>
<version>${htmlunit-version}</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-support</artifactId>
<version>${selenium-version}</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng-version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.8</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.5</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Here AspectA runs fine on method testNavigation()
AspectB runs fine on inner method call of NavigationBar.goToHelpPage() that is present under testNavigation() method.
When private method takeCareOfNavigationToHomePage() that is annotated #ChangeToIFrameA is called AspectA runs on that method and during the inner method call NavigationBar.goToHomePage() again AspectA is called instead of AspectB. AspectA call happens twice looks like an overriding is happen.
I see its happening because the private method takeCareOfNavigationToHomePage is called under login method that is already annotated with TestNG annotation #BeforeClass. Any idea how to overcome this? Please suggest a solution.
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).
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/
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.
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 ...
}