I have 2 jars, common.jar and business.jar. common.jar contains common functioanlilty shared across all modules and most important it has hibernate session factory configuration like -
.
Now, I want to refer mySessionFactory from common.jar to my business.jar because I am defining transaction information in my business.jar and transaction configuration needs HibernateSession info.
Please suggest me how to refer bean from one jar to another.
Regarding the code dependency itself (making the business module depend on the commons module for source code reuse purposes), I suggest you use a build tool (maven or gradle would be good candidates).
Regarding DI, you should define a configuration in the commons module (I suppose you already have this if Hibernate works fine in the commons module).
#Configuration
// other configurations for Hibernate, component scans, etc
public class CommonsConfig {
}
Then, in the business module, you should import the commons configuration.
#Configuration
#Import(CommonsConfig.class)
public class BusinessConfig{
}
Now the beans from the commons module should be detected by the component scan from business module (and you should be able to use #Autowire for beans from the commons module in the business module).
Related
I have a spring boot rest service that included an external project in pom as it's dependency. That external project is basically a jar that has spring AOP code.
The base package in my main application that includes this external jar with spring AOP code is x.y.z
The class in external jar where the #before advice is, is under the package a.b.c
With this class under a.b.c package, it doesn't get recognized by the main application where I want to use the spring aop implementation and apply the aspect. However, when I change it's package from a.b.c to x.y.z (which I really can't do in real life) it works fine.
I know that in spring boot service which happens to be the including service, it scans everything under root package given in the application class, x.y.z in this case and that is why aspect works fine if it's class is under x.y.z.
however, the problem is that this spring app jar will be used across multiple applications. So changing package name like this is not an option.
Is there a way to accomplish this without changing the package name of the class where spring app code is ?
Probably component scan is only activated for your application class packages by default. You can extend it to multiple packages, including the aspect package:
XML style configuration:
<context:component-scan base-package="x.y.z, a.b.c" />
Annotation style configuration:
#ComponentScan(basePackages = {"x.y.z", "a.b.c"})
Disclaimer: I am not a Spring user, only an AspectJ expert. I just knew that you can configure component scan, googled the syntax for you and hope it is correct.
Please define the bean (of jar project )inside main application. Give the #ComponentScan(basePackages = {"x.y.z", "a.b.c"}) as well as #EnableAspectJAutoProxy. Also include below piece of code.
ex:
` #Bean
public LoggingHandler loggingHandler()
{
return new LoggingHandler();
}`
Also annotate external jar code with:
`#Aspect
#Component
public class LoggingHandler {`
What #kriegaex suggests is correct. In addition to that, please make sure you are using #Component along with #Aspect. Since #Aspect is not a Spring annotation, Spring won't recognize it and hence your aspect won't be registered. So, using #Component is mandatory to getting aspects to work in Spring environment.
Spring boot provides #ComponentScan to find packages to be scanned.
I am building a library which has #RestControllers inside with package com.mylib.controller. There are other classes as well with stereotype annotations in different packages.
So, if some one is developing SpringBoot Application with com.myapp base package.
He uses my library in his application. He need to mention #ComponentScan("com.mylib") to discover stereotype components of library.
Is there any way to scan components without including library package in #ComponentScan?
As spring-boot-starter-actuator expose its endpoints just with dependency, without defining #ComponentScan. OR any default package which is scanned regardless of application base package.
You could create a Spring Boot Starter in the same style as the Spring Provided Starters. They are essentially a jar'd library with a a spring.factories file pointing to the #Configuration class to load with some other annotations on there to provide overriding/bean back off (#ConditionalOnMissingBean) and generally provide their own #ConfigurationProperties.
Stéphane Nicoll provided an excellent demo of how to build one.
https://github.com/snicoll-demos/hello-service-auto-configuration
It is also documented in the Spring Boot documentation. https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html
The library approach would also work but I see no benefit in not making it a starter. Additionally for any library/starter I'd recommend dropping the #ComponentScan and just defining the beans in a #Configuration. This will work for sterotypes like #RestController etc. will function as normal if you create an #Bean out of it in a configuration.
Spring boot starter are special artifacts designed by Spring and used by Spring.
You can check that in the source code that contains mainly a
spring.provides file :
provides: spring-boot-actuator,micrometer-core
I don't know the exact way to process in the same way as Spring Boot Starter but as probably acceptable workaround, you could define in your jar a #Configuration class that specifies #ComponentScan("com.mylib").
#Configuration
#ComponentScan("com.mylib")
public class MyLibConfig {
//...
}
In this way, clients of the jar need "only" to import the #Configuration class :
#Import(MyLibConfig.class)
#Configuration
public class ClientConfig{
//...
}
Noobish question here, but I'm struggling to make this work.
I've an old project with submodules which does not use Spring or anything, just final class and static Instance.
--- Main
------ Server
------ Business
------ Webservices
Server has a dependency with Business and Webservices.
Webservices has a dependency with Business
Server is the sub-module with the web.xml file.
I have to add a new service in Business sub-module and I want to start using Spring and dependency injection to do so, in order to start migrating the project to Spring.
(I'm not talking SpringBoot, just regular Spring).
In Business sub-module, I did:
add spring-core, spring-beans, spring-contet dependencies as well as javax.inject .
Using spring version 4.3.2
create an interface IMyService and its implementation MyServiceImpl and added the #Service annotation on the impl.
add a spring-context.xml file in src/main/resources declaring context:annotation-config and context:component-scan base-package
Then I created, in my submodule a "bridge" to try and use the Spring bean from my submodule in a non spring bean of another submodule, like described here : https://blog.jdriven.com/2015/03/using-spring-managed-bean-in-non-managed-object/
However the context never get injected.
I've tried adding in the web.xml of Server the contextConfigLocation but no dice either.
What Am I missing so that my Spring context get initialized in the Business module ?
Before the spiel, I think the question essentially boils down to this:
How can I instantiate correctly #Configuration beans from an application's XML-based configuration?
In an attempt to modularize my project and follow something of a clean architecture, I have created a Maven project composed of three modules. There is a "web" module an "interface" module and a "core" module and both web and core use Spring's Java-based configuration.
The web module declares in it's POM a runtime dependency on the core module and a compile-time dependency on the interface module. The core module is the implementation of the interface module, the latter being composed of only Java interfaces and DTOs. (This is an attempt to program to interface modules.)
When I start the web module I want all the Spring-managed beans from the core module to become known to the web module's application context. I've had some success doing this the "XML-way" by creating an XML file in the core module that looks like this:
// This xml snippet is part of the "core" module
<beans>
<context:annotation-config />
<context:component-scan base-package="com.acme.core"/>
</beans>
... and referencing this in the web module configuration like so:
// The configuration of the "web" module
#Configuration
#ImportResource("classpath*:come/acme/configuration/spring/*.xml")
public class RootConfig {}
It works but I'm not happy with the solution because I want all the configuration for the core module to be done the Java way.
So to that end, I note that Spring says one can do the following:
...#Configuration classes may be declared as normal definitions within Spring XML files:
<beans>
<context:annotation-config/>
<bean class="com.acme.configuration.spring.CoreConfig"/>
</beans>
That would be (almost) ideal if it worked because the XML file in the core module would be very lean and essentially just bootstrapping the meaty configuration in CoreConfig. However it doesn't work for me and the web module cannot find any of the beans that are defined in the core module. I think this might be because if the beans are instantiated then they are done so in a different application context or maybe because CoreConfig, being marked with #Configuration, is special and instantiating it this way from the XML file doesn't trigger the creation of the other beans it defines.
Incidentally, I'd rather have a way to do this without any XML configuration but referencing com.acme.configuration.spring.AppConfig directly from the web module is not possible since there is no compile time dependency on the code. (Sigh) Modularizing is so far proving to be more trouble than it's worth...
The following works when specified in the config class of the "Web" module in my example:
#Configuration
#ComponentScan(basePackages={"com.acme.configuration"})
public class RootConfig {}
In fact, it is what #M. Deinum said to do in a comment on the question. In this example, all com.acme.configuration packages, regardless of whether they might be in another Maven module, will be picked up and processed correctly. It is necessary then, by convention, that all configuration classes of other modules be placed in com.acme.configuration. With this approach there is no need for any XML configuration file to "bootstrap" the configuration as I was trying to do.
I have two maven projects say MvnSpring and MvnGuice.MvnSpring is working on spring and hibernate frame works.
And MvnGuice is working on google guice and mybatis. I need to combine both the features together.
Both are following singleton pattern. I need to get some class of MvnSpring in MvnGuice while coding. So that I created a jar of MvnSpring and put it in .m2 repository and give the dependacy details in MvnGuice. Now I can import classes of MvnSpring in MvnGuice classes.MvnSpring uses spring dependency injection and MvnGuice uses guice dependency injection for object creation. Now in MvnSpring flow is MSserviceImpl(implements MSservice) > MSdaoImpl(implements MSdao). Now I need to call MSService class from MvnGuice. Then at run time it shows error like MSService class is null. Then I made a guice dependency injection for MSService class in MvnGuice. Now the control reaches MSserviceImpl but now MSdao is null at here. Is it possible to start MvnSpring along with MvnGuice. I hope then I can solve the issue.
While Spring and Guice are targeted at the same problem, IoC, they take very different approaches to solve it. They differ both in functionality and in how they are configured, where Spring has bean definitions and Guice uses bindings.
Fortunately they do have common grounds in that they both support JSR-330, a standards specification that defines a set of annotations. This enables you to write your singletons and describe the injections that they need without depending on either Spring or Guice.
This way you can share your singletons between projects irregardless of the framework you use in a particular project. I would not recommend using both Guice and Spring in the same project, except if there's a clearly defined separation between them. For instance you might use Guice for a module that is used by Spring code via a defined API that hides the fact that it internally is based on Guice.
There was already mentioned JSR-330.
For some cases it can be not enough, e.g., you have code:
final String className = config.getProperty(«serviceImpl»);
// Class.forName(name) and check required interface for type safety
final Class<? extends Service> serviceClass = Reflection.classForName(className, Service.class);
final Service service = injector.getInstance(serviceClass);
In different DI environments you are supposed to support both com.guice.inject.Injector.getInstance() and org.springframework.context.ApplicationContext.getBean() implementations.
There is the draft solution sdif4j Simple Dependency Injection Facade.
The idea of this project is to encapsulate different DI frameworks logic with own abstraction to extend default JSR-330 possibilities. Note, there is no public releases yet, but you can find ideas how to solve your problem or make an internal release in a fork.
The general issue, is that your both MvnSpring and MvnGuice projects are supposed to be based on JSR-330 (instead of guice/spring annotations) and org.sdif4j:sdif4j-api (or your own abstraction; only if Injector functionality is required). It is recommended to make guice and spring dependencies optional (to compile but not export) to allow the library clients to choose the DI themselves.
In your MvnCompineGuiceAndSpring you just declare sdif4j-guice or sdif4j-spring dependency (it is similar to slf4j usage) and configure your DI environment. You can find different examples in testing subproject.
Some more notes:
Spring default scope is singleton, Guice - prototype (Spring terminology). So, if you want a prototype bean, you can use:
#org.springframework.context.annotation.Scope("prototype")
#javax.inject.Named
public class TestPrototype {
}
The Spring #Scope annotation should be ignored by guice even if spring does not present in your classpath.
Also you have to declare all your Singleton beans with #javax.inject.Named and #javax.inject.Singleton annotation to support both Spring and Guice, like this:
#javax.inject.Named
#javax.inject.Singleton
public class TestSingleton implements ITestSingleton {
public TestSingleton() {
}
}
As with #Scope annotation, you can use #ImplementedBy(#ProvidedBy) guice annotations on your code (when feasible; be careful with it, in general it is not a good practice), that should be also ignored in Spring DI (in both cases if Spring exists in classpath or not).
Hope, that's clear.