NPE on autowiring from dependent Project - spring

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
}

Related

Autowire a Repository to a library project in Spring Boot

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.

spring boot project as dependency inside another spring-boot project

I have a spring boot project(project-lib) which I am including as maven dependency in another spring boot project(my-project).
now the project-lib uses logback and i want to exclude the logback dependency in my-project.
Also currently project-lib is defined as dependency with classifier jar-with-dependencies
Is it possible to define project-lib as normal dependency instead of jar-with-dependencies.
I tried to define it as normal dependency assuming it will download all the required dependencies as project-lib/pom.xml has already defined the required dependencies to run project-lib but it did not work that way.
part of pom.xml of my-project
<dependency>
<groupId>com.xyz/groupId>
<artifactId>project-lib</artifactId>
<version>0.0.4-SNAPSHOT</version>
<classifier>jar-with-dependencies</classifier>
</dependency>

Unable to start spring-boot application after configuring spring-session-data-redis

After configuring spring-session-data-redis in a demo spring-boot project, bootRun task fails with the following message:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method redisTemplate in org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration required a bean of type 'org.springframework.data.redis.connection.RedisConnectionFactory' that could not be found.
- Bean method 'redisConnectionFactory' not loaded because #ConditionalOnClass did not find required classes 'org.apache.commons.pool2.impl.GenericObjectPool', 'redis.clients.jedis.Jedis'
- Bean method 'redisConnectionFactory' not loaded because #ConditionalOnClass did not find required class 'io.lettuce.core.RedisClient'
Action:
Consider revisiting the entries above or defining a bean of type 'org.springframework.data.redis.connection.RedisConnectionFactory' in your configuration.
What I've done (a.k.a. steps to reproduce):
1. Used Spring Initializr to create a [Gradle with Java and Spring Boot 2.1.0 M1 + Web dependency] project.
2. Followed the Spring Session - Spring Boot instructions to configure Spring Session. More specifically:
- added compile 'org.springframework.session:spring-session-data-redis'
to build.gradle's dependencies block
- configured the store type by adding spring.session.store-type=redis to application.properties file
- configured the connection
properties (in application.properties file): spring.redis.host,
spring.redis.password and spring.redis.port with relevant values
3. Executed ./gradlew bootRun from the root of the project and received the above error
Questions:
1. As far as I'm understand from the error message, RedisConnectionFactory failed to load because it can't find neither Jedis nor Lettuce drivers. Shouldn't spring-session-data-redis bring one of those drivers by default?
2. How to resolve this issue in case I want to use the Jedis driver?
3. How to resolve this issue in case I want to use the Lettuce driver?
1.
As #M.Deinum mentioned, spring-session-data-redis (version 2.1.0.M1) doesn't pull Jedis or Lettuce drivers.
2.
Add the latest Jedis driver as explicit dependency:
dependencies {
// ...
compile 'redis.clients:jedis:2.9.0'
}
3.
Either add spring-boot-starter-data-redis (which pulls in Lettuce driver) or the latest Lettuce driver as explicit dependency:
dependencies {
// ...
compile 'org.springframework.boot:spring-boot-starter-data-redis'
// OR
compile 'io.lettuce:lettuce-core:5.0.5.RELEASE'
}
There is 2 implementation of RedisConnectionFactory are comes with spring-session-data-redis
(1) lettuce (default) - https://github.com/spring-projects/spring-session/issues/789
(2) Jedis
Since lettuce & Jedis dependency are optional u have to have explicit dependency. u can put dependency to either one of it. (u can have both but Spring redis implementation stater used lettuce as a default implementation)
Example:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>x.x.x</version>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>x.x.x</version>
</dependency>

spring boot #Autowired a bean from another module

My question is how can i add a package to my list of component to scan #ComponentScan(basePackages = {"io.swagger", "com.company.project", like add it here }), but this package is in another module in my project,
here is the structure of my project :
springbootProject (maven project)/
module1(mavenProject, com.company.module1)
pom1.xml
module2(mavenProject, com.company.module2)
pom2.xml
pom.xml
in module 2 i have my main (#SpringbootAplication) where i want to #Autowired myRepository witch is in module 1
so how can i add the path
Import ModuleB on ModuleA, and you'll be able to use it.
Project
|__ Module A (com.test.a)
|__ Module B (com.test.b)
In pom.xml on ModuleA, add:
<dependency>
<groupId>com.test</groupId>
<artifactId>b</artifactId>
<version>1.0</version>
</dependency>
Then you should be able to add:
#ComponentScan(basePackages = {"com.test.b"})

Spring - Combing Java Config and Xml to reference a bean defined in legacy XML

Is it possible to configure a classpath resource for a Java bean in any other location in the classpath than src/main/resources? I have an application which picks up its configuration files from src/main/app/conf/beans.xml. I want to use the bean defined in the xml configuration in my JavaConfig configuration, how can I specify the location in a JavaConfig file, for example something like below?
#Configuration
#ImportResource("classpath:..beans.xml)
public class AppConfig{
// Reference Bean
#Autowired
private MessageLoader loader;
}
That is certainly possible. If your resources are not present in src/main/resources then, you can specify that directory in your POM.
<resource>
<directory>[your folder here]</directory>
</resource>
Reference here

Resources