I am refactoring an application using Spring by moving some shared components (a webservice client) into a library. The components cannot work on their own so still need some beans from the application that uses the library. What is the best practice for this?
I have created a #Configuration class so the application only needs to #Import it to use the library, but the application also needs to supply a Jackson ObjectMapper and a Settings object containing how to contact the webservice. I autowire the ObjectMapper and Settings beans into various beans used in the library. The application uses the library by injecting the Client into its code and calling it.
This works, but I'm not sure it's the right style. In IntelliJ IDEA as I develop the library, it complains that the beans the library injects don't exist with a red underline, which is true, they don't exist. But normally when I see red all over files that cannot be resolved, that tells me maybe I'm not doing it the right way.
The library needs to be used with applications using Spring 3 and 5. What is the proper way for a library to ask for things like ObjectMapper when it's not appropriate to define its own (because the app will already have Jackson), and "proprietary" beans like the Settings object?
Your question is a bit broad but hopefully I can give you a hint to the right direction.
The components cannot work on their own so still need some beans from the application that uses the library. What is the best practice for this?
First: This components should use an interface instead of some concrete beans.
Second: If you have a reusable library then this typical needs some configuration, that can not been part of the library itself because it depends on application that use that library
Third: because of second (and first): your library should not been based on any form of auto wiring, instead your library should been based on explicit (or default) configuration.
And this solve the problem. Use interfaces and an explicit configuration of your library in your application. As well as add an good documentation of the needed configuration to your lib.
Using inspiration from #Kayaman and #Ralph, I decided it's not appropriate to expose Spring as a part of a library to be used directly from the application's context. I realize now it's also not appropriate because the library could define duplicate "private" beans it did not want to expose. I was overthinking it. If I wanted to use Spring, I found out I could do this:
public class Factory {
public static Client createClient(ObjectMapper mapper, Settings settings) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerSingleton("mapper", mapper);
beanFactory.registerSingleton("settings", settings);
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(beanFactory);
ctx.registerBean(ClientConfiguration.class);
ctx.refresh();
return ctx.getBean(Client.class);
}
}
Essentially, it's OK to use Spring as an implementation detail. Since the configuration I made exposed only one bean, it makes sense as a factory method. In the application I would create a method like this:
#Bean public Client makeClient(ObjectMapper mapper, Settings settings) {
return Factory.createClient(mapper, settings);
}
Of course the Bean method would have ObjectMapper and Settings injected in from the application's context, or could be inline constructors for ObjectMapper/Settings.
Instead, what I decided was since the client had few enough beans and none were lazy, I just removed Spring annotations entirely and just built the object graph by hand in almost as much code as the spring context took. Now the library has the benefit of not requiring Spring at all at runtime, in a supposed non-Spring application.
Related
I am developing a Keycloak Based application which is embedded inside of a Spring Boot project. More specifically, I have made a setup based on the approach described here: Link.
I am using the default static method KeycloakApplication.getSessionFactory() in order to obtain a KeycloakSessionFactory that can be used to instantiate a KeycloakSession. However, the default KeycloakSessionFactory seems to be instantiated some time after the application is started, making it difficult to inject the factory as a Spring Bean as well as to use it in (unit) test scenarios. I would like either to construct the factory myself manually, or to have a way of making sure that I know when it is available for me to use. I have tried to use both the Lazy and DependsOn annotations, and I am now all out of ideas.
I'm working in a webapp and this is the first time that I'm using Java based configuration. I have a bunch of class to configure all:
ApplicationContext
PersistenceContext
SecurityContext
WebAppInitializer
WebMvcContext
Now I'm defining Spring Data repositories and the service layer so I need to inject the repositories there. Normally I would use Autowired but I've read that it is preferable to define the injections manually so the question is, where?
Maybe neither of the previous configuration classes is suitable for such task but, do I have to create a single class to define all the injections or is better to have on for each function? What happens if the project grows too much?
I think that the main question would be what is best way to organize dependencies in a Spring project. What do you do?
I add here an image of the structure of the project as a petition. I'm trying to decouple layers and now I need to inject UserRepository to UserService.
No, I would not define a single class to do all the injections. All your classes are coupled that way.
I don't understand what "define the injections manually" means. You have to specify them in either XML or annotations. There's no other way that I know of.
You don't say if you're using XML or annotation configuration. I find myself using the latter more of the time, with only enough XML configuration to tell the Spring app context to scan for annotations.
The Spring idiom would have you specify your configuration in layers if you're using XML. It's a moot point for annotations, because they go into your source code.
Your application will read the Spring context on start up, instantiate all the beans, and wire together the necessary dependencies. You're good to go from then on.
I disagree with the link you provided. Avoid autowiring? No.
The article said that he recommends using XML configuration for large projects. This is a very small project at this point. It seems to me that auto wiring with annotations would be fine even by the article's author's words.
Overview
Using
Spring 3.0.1 (annotation configuration)
Current configuration is using CGLib as proxy creator but this is not my preference
Transactions are annotation configured without any special settings
All configuration is done with annotations (#Service, #Transactional, #ManagedResource, #Inject, etc.)
Hibernate 3.5 (entities are annotated with javax.persistence)
Guidelines highlights
Every bean annotated with #Repository or #Service must have an interface
Constructor DI (when re-configuration isn't required)
Constructor has default visibility (Foo(Bar bar) {...})
Bean fields are final (when re-configuration isn't required)
Leads to no default constructor
Implementations are default visible with final modifier (final class Foo)
The Problem
CGLib can't proxy final classes
CGLib requires default (empty) constructor
Some services are required to be exposed via JMX
MBean exporter can't work unless proxied by CGLib
Some #Transactional #Services are accessed via facade service which requires more than one service to include in the facade transaction (e.g. Observer service over 2 application components)
Some interfaces have more than one implementation (which currently distinguished by #Qualifier)
Future guideline (or nice to have feature) - each application module will have beanRefContext.xml file to configure its internal application context
When I used to work with XML configuration I was able to enforce all the guidelines I presented above, but when switching to annotations it seems like Spring is misbehaving.
Developers in my group prefer annotation configuration (I seems easier to wire and write new code), but I've noticed all kind of "hacks" they introduce to the code to prevent from dealing with Spring application context failures.
The Question(s)
Are there best practices I should follow when using annotation configuration?
When using more than one implementation per interface (trying to reduce the use of #Primary or #Qualifier)
When using #Transactional
When using #ManagedResource
When using a combination of the above
Is there a way of stop working with CGLib, keep the annotation configuration and still be able to export my MBeans with annotations?
What is the suitable implementation for keeping most (preferably, all) of my guidelines?
I came up with the following solution (to questions #2 and #3) to be able to enforce my design guidelines and keep using annotation based configuration:
Each dependent project (Maven module) has it's own ApplicationContext
Every dependent project application context is defined in beanRefContext.xml
These application contexts are loaded in hierarchy using Spring context hierarchy mechanism.
This step is actually not fully supported by Spring and requires additional work
Since my application is layered, I could disable CGLib on all my modules besides the JMX layer (I can live with it :-) ).
The above steps also enabled me to reduce the execution time of Spring aware tests (every module loaded only a sub-set of beans).
As a practical guideline (for question #1), if an interface has more than one implementation, I place #Primary on the widely used one and other clients, requiring another implementation, wire the bean using #Qualifier.
Answer to point 2)
You could use AspectJ instead of CGLib.
I've seen at least three ways of acquiring dependencies in a Java object without coupling the object to the creation of the dependency;
Dependency Injection
- some framework injects a required object into another object based on an external configuration, example: Spring managed beans
Dependency Lookup
- a class looks up a required dependency in some kind of directory service, example: JNDI lookups in a Java EE container
Static Factories
- an object in a global scope provides instances on demand - the standard Java SE APIs seem to be littered with these, example: java.util.Logger.getLogger(name), java.util.Calendar.getInstance()
What guidance can you provide as to which is most appropriate for a situation?
I prefer dependency injection, because the object need not know how it acquires the references it needs.
Dependency lookup still requires the object to know about the lookup service and its URL.
Static factories are similar to lookup services.
I prefer dependency injection.
When I talk about DI with Spring Framework I see following
It's supported by IDEs (error check, visualization).
You can setup other needed stuff like AOP, properties loading, ...
You have big config possibilities - XML, annotation, JavaConfig
Can be use also in desktop application.
These outbalance every negatives like dependency on another library. Why should I use another approach?
This really depends on the context. If you are writing a self-contained Maths API you might want to use static factories because the code will be less verbose, setup-free and maybe more efficient. If you need to access/provide a remote dependency, a JNDI/LDAP lookup, or ESB messaging would work well. For injecting your services/DAO's/datasources into your typical enterprise server code you'd be better off using one of the common D.I. frameworks like Google Guice or Spring.
There is no single 'best' solution in software design; it's always a tradeoff.
I'm writing a java library that will be used by an existing application. I'm using dependency injection so testing is easier, and I'm familiar with Spring so I was planning to use it to manage the dependency injection while testing. The applications that will eventually use the library are not Spring-based, however, nor does it use any IoC/DI container of any sort currently. My question is, what's the best approach for injecting dependencies if Spring or Guice are not used? Should I consider something like a factory method to instantiate and wire the objects? The dependencies are all inside the library, so it doesn't seem appropriate to have the application instantiate each dependency to create the main object.
what's the best approach for injecting dependencies if Spring or Guice are not used?
If your library was written in a DI-friendly idiom. It should be fairly easy to use as a straitforward java API. Think of your past experience with spring. There are several libraries out there that fit perfectly with the spring model but were written before spring time. I don't see nothing bad with a new followed by a couple of setXX followed by a call to the real work method. Just be extra careful, since, among other things, your client can forget to call thouse init methods that spring reliably calls.
Should I consider something like a factory method to instantiate and wire the objects? The dependencies are all inside the library, so it doesn't seem appropriate to have the application instantiate each dependency to create the main object.
Let the client application decide that. You are providing a library. Let the API client wire its own objects. Provide an example. Later, that same example can be used to make the factory method on the client's domain. Maybe the client application has it's own way to configure itself, and it would be desirable if the API your library provides to be flexible enough to take advantage of that.
Or maybe you can include guice. The licence is Apache. Just like a whole piece of Java itself.