Inject bean from a different folder - java

I have a project structure that looks like this:
In My Groovy folder contains a class marked with #Component that I Want to inject in another class inside the java folder. However spring can't find the bean to inject, when I move the class marked with #Component to the java folder it works fine. How can I make spring aware of the groovy folder?

You can use #ComponentScan at your Spring application (annotated with #SpringBootApplication) to scan components from other packages.
#ComponentScan(basePackages = "com.stackoverflow.other.package")
See https://www.baeldung.com/spring-component-scanning.

Related

Spring Boot Application add external library component scan

I have a spring boot app, which has a library as a dependency. In this library I have several #Component and #Configuration classes, which are not scanned by Spring Boot app. I would like to add them to component scan, but I am not able to
How can this be achieved correctly? I think adding #ComponentScan to MainApp class, annotated with #SpringBootApplication will override the default config
Thanks!
#SpringBootApplication Annotation is the combination for #Configuration, #EnableAutoConfiguration and #ComponentScan
We can also use basePackages for scan based on requirement.
For example common package is com.example so directory will be com -> example and sub packages. So for the project there will be different packages for the different modules like controller, service, dto, repository etc...
If we want to use any package for the component scan then we can use like below script.
Hierarchy will be :
com.example.controller
com.example.service
com.example.repository
So basePackages will be look like this :
#ComponentScan(basePackages = "com.example")
Because com.example is only the path/package which is common for all other packages. So we can use like this.

What happens when we define a bean inside the test folder?

I have defined a class with annotation #Configuration and some bean methods in it. This class is inside the test folder. So when I run the application will these beans be loaded by SpringBoot?

How use #ComponentScan in Spring Boot to load classes from jar and a wildcard that works like the default?

When I add #ComponentScan to my main class and pass the `basePackages' with the packages from my external jar, it no longer scans my project's packages. I can add those packages manually like:
#ComponentScan(basePackages={"com.jar.classes","com.project.classes"})
But this means I'll have to manually keep that updated. Is there a way to say:
Scan all packages like the default
Add the jar's packages for scanning as well
You could create a simple configuration class which is in your project's packages that are picked up by the default component scan which includes a specific component scan for your external components.
i.e.
#Configuration
#ComponentScan(basePackages = {"com.jar.classes"})
public class ExternalComponentConfig {
}
Or it might actually be possible to include 2 component scans in your base config class like:
#ComponentScan
#ComponentScan(basePackages={"com.jar.classes"})
But i'm not 100% on that working whereas I am 100% on the first solution.

Spring Annotations in XPages Java classes

I'm trying to use Spring annotations in Domino XPages Java classes. Spring works when I'm defining beans in the configuration file. However I fail to use the annotations.
To illustrate the problem, I have created two simple empty classes annotated with #Component annotation - com.geo168.a.B (#Component public class B {}) and com.geo168.a.C (#Component public class C {})
The first one I have created in Eclipse, packed and added to the application in a jar. The second one I add directly in Code/Java section.
I add a component-scan tag in the configuration file: <context:component-scan base-package="com.geo168.a"/> and try to instantiate the classes:
ApplicationContext ctx = new ClassPathXmlApplicationContext(SPRING_CONFIG);
// class defined in the jar, works ok
com.geo168.a.B b = ctx.getBean(com.geo168.a.B.class);
// class defined in Code/Java, throws exception
com.geo168.a.C c = ctx.getBean(com.geo168.a.C.class);
I get an error: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.geo168.a.C] is defined
Spring has found the annotated class only in the JAR file. It works if I add the bean explicitly to the configuration file:
<bean class="com.geo168.a.C"/>
A similar post: Is possible to add annotation #ManagedBean in XPages? seems to address only the particular JSF annotations (that do not work, because they are not implemented).
In the Spring documentation: http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-scanning-autodetection I find a note: The scanning of classpath packages requires the presence of corresponding directory entries in the classpath. When you build JARs with Ant, make sure that you do not activate the files-only switch of the JAR task.
Could this be somehow related? I do not know in what form Domino deploys the classes internally.

Should the service beans defined in the jar library be instantiated by the jar library configuration or by the client war application configuration?

I have a library as a jar packaging Maven project which offers services.
The #Configuration class to instantiate service beans:
#Configuration
public class JpaService {
#Bean
public UserRoleServiceImpl userRoleService() {
return new UserRoleServiceImpl();
}
#Bean
public UserServiceImpl userService() {
return new UserServiceImpl();
}
}
I reckoned I needed to have the beans instantiation outside of the jar archive.
So I had a copy of this class in the test part of the project, and another copy in another war packaging Maven project using the library.
But what if I instantiated the services in the jar library itself. I would need to only do it once, be it for testing or for all client projects using it.
UPDATE: Two questions...
Should all component scanning only be done from the war ? Or should the jar service components be scanned from the jar ?
And what if two components (one in the jar and one in the war) have the same class name in the same package ?
I dont think i fully understand your question, but if you are aiming to add beans to your application context that is outside the jar then what you have to do is use the #ComponentScan annotation, and specify the package you want to scan, the package can be in a different jar, the only thing required is that you anotate the clases you want to include with #Service, #Componenet or even #Configuration
example:
#Configuration
#ComponentScan(basePackages={"com.somepackacge.controller",
...
you can include as much packages as you like.
By the way dont copy your clases from one place to the other, maintining that will be a headache in the futute, if you want to include your configuration in your tests you can always do :
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyConfigClass.class)
Where MyConfigClass is the class u used before with the component scan
Hope it helps

Categories