Autowire a Repository to a library project in Spring Boot - spring

I'm working on a Spring Boot multi-module project. I have created separate modules as follows
com.foodshop.api - (this is a Spring Boot project, the starting point and both com.foodshop.application and com.foodshop.persistence are added as dependencies here)
com.foodshop.application - (the application layer where I have the business logic, thi s is a library project and spring-boot-starter and com.foodshop.persistence are added as dependencies here)
com.foodshop.persistence - (this is where the repositories defined, spring-boot-starter-data-mongodb is added as a dependency in this project)
All 3 project mentioned above are wrapped inside a parent pom maven project and the parent pom.xml looks as follows;
<?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.foodshop</groupId>
<artifactId>foodshop-backend</artifactId>
<version>0.0.1</version>
<packaging>pom</packaging>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<modules>
<module>foodshop.persistence</module>
<module>foodshop.application</module>
<module>foodshop.api</module>
</modules>
</project>
The project builds without any errors. The application class of foodshop.api I have annotated as follows so that it can see the dependencies in other modules
#SpringBootApplication(scanBasePackages = {"com.foodshop"})
But when I try to run the API project, it looks like the foodshop.application fails to find and autowire the repositories defined in foodshop.persistence
I get an error as follows;
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.foodshop.application.MealManager required a bean of type 'com.foodshop.persistence.repository.MealRepository' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.foodshop.persistence.repository.MealRepository' in your configuration.
I have properly annotated MealRepository with the #Repository annotation but I feel like I have missed something important.
It would be very much appreciated if I can get some help on this issue.

After more than 20 hours reading and following the trial and error approach, I was able to identify the issue. As per the Spring official documentations
If your application also uses JPA or Spring Data, the #EntityScan and
#EnableJpaRepositories (and related) annotations inherit only their
base package from #SpringBootApplication when not explicitly
specified. That is, once you specify scanBasePackageClasses or
scanBasePackages, you might also have to also explicitly use
#EntityScan and #EnableJpaRepositories with their package scans
explicitly configured.
Since I use spring-boot-starter-data-mongodb, I annotated my Application class as follows;
#SpringBootApplication(scanBasePackages = {"com.foodshop"})
#EnableMongoRepositories(basePackages = "com.foodshop.persistence")
public class Application {
// main method goes here.
}
#EnableMongoRepositories annotation did the trick.

Related

Migrate parent pom to gradle in a spring boot project

In my spring boot project the pom.xml has a <parent> tag which refers to the parent pom.
<parent>
<groupId>com.sintara.codify.ems</groupId>
<artifactId>ems-parent-pom</artifactId>
<version>1.0.0</version>
</parent>
I am migrating my project from maven to gradle.
How do I take care of this or parent pom concept in Gradle.
Is there any way to do it without converting it into a multi project setup.
In gradle we have similar usage. We can create a parent.gradle file in project root path, and declare common dependencies in it. just like below:
ext {
parent = [
"ems" : "com.sintara.codify.ems:ems-parent-pom:1.0.0"
]
}
And then in your child gradle file, you can use it:
dependencies {
implementation rootProject.ext.parent["ems"]
}

Call hierachy of properties in pom.xml

I have a maven project with multiple nested projects. All of them do always have the same version. Untill now, if I want to increase the version, I went through all pom.xml files and changed the version number.
Now, I wanted to outsource the version to the properties tag of the parent pom.xml file. It works, for all nested projects, but not for the parent pom itself.
In which order are the attributes in the pom.xml called? I can not reference
the project version in the parent pom.xml file.
The code snippet shows the parent 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">
<groupId>com.my.project</groupId>
<artifactId>my.project</artifactId>
<packaging>pom</packaging>
<version>${projectVersion}</version>
<properties>
<projectVersion>1.0.0</projectVersion>
...
</properties>
<modules>
<module>my.project.service</module>
<module>my.project.db</module>
...
</modules>
I expect the pom to take the version number defined in the properties. But it failes building with the error invalid reference format
I expect the pom to take the version number defined in the properties.
But it failes building with the error invalid reference format
By running a maven goal from the parent project, maven first binds the artifact/group/version in the current build process, so it uses the version defined here :
<version>${projectVersion}</version>
I can not reference the project version in the parent pom.xml file.
In this case, you could "cheat" by creating an aggregator/multimodule project that defines a not used/fake version (1.0-NOT-USED for example) that has as unique module the parent pom. When you build the aggregator/multimodule project, you can now pass as parameter the version to use in the parent project and all its modules.
As a side note, to use a central version for a set of projects, you should use the flatten maven plugin that relieves you from the hell version management.

NPE on autowiring from dependent Project

This is my project structure,
Parent Projectt -->
pom.xml
(sub modules core,web,services)
core prj -->
pom.xml
web prj --> has core,services dependency and has ComponentScan for com.aaa.bbb
pom.xml
services prj --> has core, web dependency
pom.xml
client Project -->
pom.xml (sub modules xxx,yyy)
xxx -->
pom.xml
yyy --> has core dependency
pom.xml
xxx and yyy jars are used in core project and war is built by web project.
when i autowire services/repositories in yyy project i am getting NPE for services/repositories.
Can any one please let me know how i can autowire services/repositories in yyy project from core project services/repositories?
Thank you,
To be able to autowire the bean from library, you have two options:
If you have access to the library code (I think this is your case):
1.1 Add annotation to mark which class is bean (using #Component, #Service,...)
1.2 In your configuration class (class which have #Configuration or #SpringBootApplication or #ComponentScan...), add path of xxx and yyy project to the classpath
#Configuration
#ComponentScan("com.my.package.xxx,com.my.package.yyy")
public class YourApplication
If you don't have access to the library code
2.1 In your configuration class, create a #Bean annotated method and initialize your bean here.
#Bean
public XRepository getXRepository() {
return new XRepositoryImpl(); // Here is your initialization logic
}

vertx 3.5.1 missing classes

I started to look into developing with VertX, and I stumbled into problems with some classes that couldnt be resolved. I am posting a simple example.
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>demo.rabbit</groupId>
<artifactId>rabbitmq-client</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>3.5.1</version>
</dependency>
</dependencies>
</project>
java code
import io.vertx.core.AbstractVerticle;
import io.vertx.core.AsyncResult;
import io.vertx.core.json.JsonObject;
public class RabbitMQVerticle extends AbstractVerticle
{
#Override
public void start() throws Exception {
AsyncResult ar;
JsonObject jo;
}
}
If I leave it like this, the compiler cannot resolve the AsyncResult and JsonObject imports, and thus cannot resolve both types.
In the external libraries view, those classes appear as part of the io.vertx.core library but the icon next to them indicates that they are missing from the library.
If I replace the vertx.core version to 3.5.0 in the pom file everything works great, switch back to 3.5.1 and nothing works again.
It's also my first time using Maven, what am I missing?
Couldn't find any useful information anywhere on the web
The mentioned classes are parts of the core Vert.x library. Core blocks never get deleted in mature libraries.
Here down the AsyncResult class for example under both versions:
AsyncResult under 3.5.0 version
AsyncResult under 3.5.1 version
Indeed I think even when changing the library version, your project still compiles (using cmd line or using IntelliJ IDEA) but you are facing a UI highlight issue with you IDE.
You can try to:
Re-import all Maven modules using the Maven Projects Tool Window
Clean the system caches and restart the IDE

spring boot fails to run - IllegalAccessError on startup

I have a strange issue and that I have not been able to resolve. I am trying to use the sample JPA sprint boot (v0.5.0-M6) project as a starting point for an application I am writing. I grabbed the JPA sample and got that to run locally. I then proceeded to add my code into that project. I imported into eclipse and run as spring-boot. Then I get this error:
Exception in thread "main" java.lang.IllegalAccessError: tried to access class org.springframework.core.io.DefaultResourceLoader$ClassPathContextResource from class org.springframework.boot.context.embedded.EmbeddedWebApplicationContext
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getResourceByPath(EmbeddedWebApplicationContext.java:386)
at org.springframework.core.io.DefaultResourceLoader.getResource(DefaultResourceLoader.java:100)
at org.springframework.context.support.GenericApplicationContext.getResource(GenericApplicationContext.java:211)
at org.springframework.boot.context.initializer.ConfigFileApplicationContextInitializer.load(ConfigFileApplicationContextInitializer.java:192)
at org.springframework.boot.context.initializer.ConfigFileApplicationContextInitializer.load(ConfigFileApplicationContextInitializer.java:134)
at org.springframework.boot.context.initializer.ConfigFileApplicationContextInitializer.initialize(ConfigFileApplicationContextInitializer.java:121)
at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:403)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:287)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:749)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:738)
From what I can tell, this is the wrong application context, since I am not using XML configuration but annotations to drive the configuration. Spring boot is automatically selecting this one and I need to tell it not to use the above. At least that is what I think I need to do.
I did search here and in the spring.io forums but no one seems to have the same issue.
Question: What drives the selection of an application context with the auto configuration?
What should I be looking at to resolve the above issue? What else do I need to provide to here help debug the auto configuration issue?
TIA,
Scott
I got the same problem.
if you use maven check your pom.xml
remove conflict version in Spring Lib.
<properties>
<hibernate.version>4.2.0.Final</hibernate.version>
<mysql.connector.version>5.1.21</mysql.connector.version>
<spring.version>3.2.2.RELEASE</spring.version>
</properties>
i remove this line
<spring.version>3.2.2.RELEASE</spring.version>
and in maven dependency just
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
Hope this help.
I was facing the same problem, and solved fixing the referencing to the boot-starter-parent pom.
At the pom.xml file I used:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>0.5.0.M6</version>
</parent>
I have some urgent issues to fix now, so I didn't inspected this parent pom to see what's so important here, but I hope this can help you - don't forget to verify the version you're using!

Resources