How to autowire #service from external Jar in Spring - spring

I am developing two spring based application(Ex app1 and app2) fully on Java configuration with Maven and no XML config.
Through Maven -WAR plugin , I have created Jar reference of app2 and using mvn install:install file I have binded the app2 jar with app1.
app2 - Its used to fetch inforamtion from data source.
I have autowired the app2 serive in app1 implementation class to fetch the details which was annotated with #Service in app2 application.
My first doubt is:
Both app1 and app2 have separate AppConfig.java file.Is it possible to simply autowiring one of the #Service which is availble in Jar format or else I need to define or import App2's AppConfig java file into App1's AppConfig.jave file.
I have tried with the simple autowired the external JAR #Service class and ended with error.
Kindly help me on what needs to be done to autowire external Jar's #Service to the
implementation class.
Below is my App1 repository class
#Repository
public class VehicleRepository {
#Autowired
VehicleService vehicleservice;
public Map<String, item> getAllTypes(String type) {
Vehicke vehicle = vehicleservice.getAllVehicle(type);
// handle response here...
} catch (Exception ex) {
// handle exception here
} finally {
}
return vehicleDetails;
}
}
VehicleService is available in external Jar.
VehicleService Class:
#Service
public class VehicleService {
public VehicleService() {
}
#Autowired
PortRepository portRepository;
#Autowired
MessageSource messageSource;
public Vehicle getAllVehicles(String type) {
List<Vehicle> cehicles = portRepository.getPorts();
return vehicle;
}

Let's make it simple.
Your App1 depends on App2.
So you use #Import(App2Config.class) class App1Config {}, that's it.
And by the way, instead of tricks with 'mvn install:install file' you can just use parent pom.xml with modules app1 and app2, and declare dependency of module app1 on module app2 in pom.xml <dependencies> section. You then run 'mvn install' to build your project.
See an example here: http://books.sonatype.com/mvnex-book/reference/multimodule.html

Related

Scan of fiegn client present in other package jar

We have one custom jar which has fiegn client in com.pack.mav.tru.client package of jar.
Now this jar is imported using pom.xml in our spring boot application.
In this main application we added the component scan with base packes and also that jar package.
Yet we see null object, when we autowire that fiegn client in that jar one class.
What we are missing, please help.
package com.pack.mav.tru.client;
#FeignClient(name = "user")
public interface UserClient {
public void getUser(#PathVariable String id);
}
package com.pack.mav.tru.service;
public class ProductService {
#Autowired
userClient userclient;
public void method(string id) {
userClient.getuser(id); ---> Here userClient is null
}
The above classes are present in one jar
We import same jar in our main spring application and added scan in main application class as below.
#ComponentScan(basePackages = { "com.mav.pack.*", "com.pack.mav.tru.client.*"})

How to get #Configuration files in Spring to run

I'm writing a micro service using dependency injection, and I have a Java class annotated with #Configuration which creates all my beans. However, my autowired fields are not detecting the beans. How do I get my #Configuration class to run before the application starts?
I tried annotating the classes with the Autowired fields as #ContextConfiguration(classes = Config.class), but this didn't work.
My spring configuration file:
#Configuration
public class Config {
#Bean
public AmazonDynamoDB amazonDynamoDB() {
return ...
}
#Bean
public DynamoDBMapper dynamoDBMapper(AmazonDynamoDB amazonDynamoDB) {
return ...
}
}
I expect the Configuration file to be run and the beans injected, but the beans are not being detected.
There's no main method, since I'm writing this in a service which is created using dependency injection in another service. I'm not sure where I'd tell my application to use my Config file.
probably place a #EnableConfigurationProperties( {Config.class}) above your #SpringBootApplication main class.

How can I register an auto-implemented repository located in a dependency as bean?

I have a module A with a project dependency of module B:
A's build.gradle
dependencies {
....
compile project(":B")
}
In module B, I have this interface:
#Repository
public interface MyRepo extends CrudRepository<User, String> {
//some methods
}
In module A, I have this configuration class:
#Configuration
public class MyConfig {
#Bean
public MyRepo provideMyRepo() {
//???
}
}
How can I export MyRepo bean in module A?
I have tried using #ComponentScan and #EnableJpaRepositories:
#Configuration
#EnableJpaRepositories(basePackageClasses = MyRepo.class)
public class MyConfig {
#Autowired
public MyRepo myRepo;
}
But bean cannot be found:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean found for dependency
You can either #EnableJpaRepositories the package that MyRepo is contained in.
Or add a configuration is in Module B which will scan the required pacakges for the Repository for you and use the Import to pull the Configuration into A.
If it's a Spring Boot project you have the added functionality of Auto-configurations, https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html
Finally, If the repository is already registered you can just use it as normal.
You don't need a new configuration for that repository since it is already registered with Spring. You can just inject it directly in your client classes in A module:
#Component
public class MyComponent {
#Inject
private MyRepo myRepo;
// your code using myRepo
}
If Spring says it can't find the bean, you need to check the autowiring configuration you have, so check that your scan path contain the repository class in B (change that using #ComponentScan or )
See this example

Spring does not load data beans (#Repository) from dependency [duplicate]

I have a myapp parent pom type maven project with myapp-core and myapp-web modules. myapp-core module is added as dependency to myapp-web.
All the classes in myapp-core module reside in root package com.myapp.core and all classes in myapp-web module reside in root package com.myapp.web
The main Application.java is also in com.myapp.web package. As my core module root package is different I am including common base package "com.myapp" for ComponentScan as follows:
#Configuration
#ComponentScan(basePackages="com.myapp")
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Now the surprising thing is if I run this app using Run As -> Spring Boot App it is working fine. But if I run it as Run As -> Java Application it is failing with error saying it can't found beans defined in myapp-core module.
If I move my Application.java to com.myapp package it is working fine.
It should work even if i run it as Java Application also, right?
After enabling debug log level for spring and going through extensive logs I found that scanning for various components like JPA Repositories, JPA Entities etc are depending on the Application.java's package name.
If the JPA Repositories or Entities are not in sub packages of Application.java's package then we need to specify them explicitly as follows:
#Configuration
#ComponentScan(basePackages="com.sivalabs.jcart")
#EnableAutoConfiguration
#EnableJpaRepositories(basePackages="com.sivalabs.jcart")
#EntityScan(basePackages="com.sivalabs.jcart")
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
With the above additional #EnableJpaRepositories, #EntityScan I am able to run it using Run As -> Java Application.
But still not sure how it is working fine when Run As -> Spring Boot App!!
Anyway I think it is better to move my Application.java to com.myapp package rather than fighting with SpringBoot!
I have the same problem. Only adding the #EnableJpaRepositories annotation can solve the issue. I tried to define basePackages in #SpringBootApplication, to no avail.
I think the package of the Application class is fed to the scanning process of JpaRepositories, but other packages defined in #SpringBootApplication are ignored.
It looks like a bug/improvement of Spring Boot.
I had a similar issue with Redis repositories that was fixed in a similar way:
#Configuration
#EnableConfigurationProperties({RedisProperties.class})
#RequiredArgsConstructor
#EnableRedisRepositories(basePackages = {"com.example.another"})
public class RedisConfig {
private final RedisConnectionFactory redisConnectionFactory;
#Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
template.setConnectionFactory(redisConnectionFactory);
template.afterPropertiesSet();
return template;
}
}

Consider defining a bean for jpa repository

My project structure is as follows:
java/com.company.foo/container/configuration/
This folder contains
#ComponentScan({"com.company.foo.module.project",
"com.company.foo.module.user"})
#Configuration
#EnableScheduling
#Import(value = {
SecurityConfiguration.class})
public class ApplicationContextConfiguration {
}
My ResourcePlannerApplication is in this folder:
java/com.company.foo/container/
and has following annotations:
#Import({ApplicationContextConfiguration.class})
#SpringBootApplication
Now I have two modules project and user with both the same structure:
java/com.company.foo/module/user/dao/
This folder contains:
public interface UserRepository extends JpaRepository<UserEntity, Long> {
UserEntity findByUsername(String username);
}
now when I start the app it tells me:
Consider defining a bean of type 'com.company.foo.module.user.dao.UserRepository' in your configuration.
I'm not seeing the problem because the ComponentScan is scanning all the folders?
JPA repositories are not picked up by component scans since they are just interfaces whos concrete classes are created dynamically as beans by Spring Data provided you have included the #EnableJpaRepositories annotation in your configuration:
#ComponentScan({"com.company.foo.module.project",
"com.company.foo.module.user"})
#Configuration
#EnableScheduling
#EnableJpaRepositories("com.company.foo.module.user")
#Import(value = {
SecurityConfiguration.class})
public class ApplicationContextConfiguration {
}
Plog's answer is correct.
I just want to add that, similar solution is applicable for Mongo Repositories as well (where we have interface as a repository).
Suppose, repository package is:
package com.example.respository;
Enable mongo repositories in spring application code, like below:
#EnableMongoRepositories("com.example.repsoitory")

Resources