We are using a custom DataSource which achieves multi-tenancy. (We have a single DataSource bean which acts like a proxy to other datasources, and the tenant context is set using ThreadLocal variables. My requirement is to get the metrics of the individual datasources proxied by that single DataSource Bean.) Basically, i need to somehow add additional metrics. It seems like the best way would be to extend DataSourcePublicMetrics, since PublicMetricsAutoConfiguration conditionally creates this bean. The problem is that the fields in DataSourcePublicMetrics are all private making reuse difficult. The only solution i see is hide all the internal variables and override the public methods. Is there a better way? I'm using spring-boot 1.2.2.RELEASE.
Use composition instead of inheritance.
MyCustomMetrics implements PublicMetrics
Any bean the implements PublicMetrics is picked up by the actuator to be exposed at /metrics. DataSourcePublicMetrics implements this interface.
You then inject the DataSourcePublicMetrics bean into MyCustomMetrics (this could even be your custom DataSource, but probably better to create a different class). Implement the contract of PublicMetrics.
public Collection<Metric<?>> metrics()
Just defer it to the DataSourcePublicMetrics implementation, and also add whatever custom metrics you want.
Related
I have a case where an Spring AutoConfiguration class is getting its dependencies through field injection and creating and exposing certain beans after interacting with them.
I would like to override one of its dependencies so the exposed beans are initialized in the way I expect.
Obviously I can disable the Autoconfiguration class and duplicate it completely locally with my desired dependency, but that would not be a maintainable solution since the amount of behaviour to reproduce is huge, and it might break on each spring update.
Is there any easy mechanisme to let the autconfiguration be loaded, and later on use the BeanFactory or something to reinject a particular instance into a particular bean?
I cannot guarantee that this is the ideal solution since this is for topics, instead of classes, but for most cases, it will do the trick.
The AutoConfiguration can be disabled in one topic, and any bean in the topic can be initialized using a particular method in the class Configuration (as usual).
List of AutoConfigurations classes (=topics)
Syntax (to exclude from autoconfiguration):
#Configuration
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
#bean
public SpecificClass getSpecificClass() {
//init the instance as you want
}
}
I am wondering what is the current best practice as to the use of factory pattern within the context of Spring framework in using dependency injection. My wonder arises about whether the factory pattern is still relevant nowadays in light of the use of Spring dependency injection. I did some searching and see some past discussion (Dependency Injection vs Factory Pattern) but seem there is different view.
I see in some real life project in using a Map to hold all the beans and rely on autowiring to create those beans. When the bean is needed, it get it via the map using the key.
public abstract class Service {
//some methods
}
#Component
public class serviceA extends Service {
//implementation
}
#Component
public class serviceB extends Service {
//implementation
}
Map<String, Service> services;
But I see there is some difference among the two approaches.
Using the above method, all beans are created on application start up and the creation of object is handled by the framework. It also implies there is only one bean for each type.
While for factory pattern, the factory class creates the object on request. And it can create a new object for each request.
I think a deeper question may be, when Spring framework is used in a project, should it be strived to not create any object inside a class, which means the factory pattern ( or any creational design patterns?) should not be used, as Spring is supposed to be the central handler of the objects dependency ?
The answer to this question can be really deep and broad, I'll try to provide some points that hopefully will help.
First off, spring stores its beans (singletons) in the ApplicationContext. Essentially this is the map you're talking about. In a nutshell, it allows getting the bean by name, type, etc.
ApplicationContext, while being a really important concept, is not the whole Spring, in fact Spring framework allows much more flexibility:
You say, using a map implies that all the beans will be created at the beginning of the application and there is one instance of the bean.
Spring has a concept of Lazy beans, basically supporting a concept of beans being actually created only when they're required for the first time, so Spring supports the "delayed" beans initialization
Spring also allows more than one instance of a bean per type. So this map is more "advanced". For example you can create more than one implementation of the interface and use declare both as beans. As long as you provide enough information about what bean should be injected to the class that might use them (for example with a help of qualifiers suppored in spring), you're good to go. In addition, there are features in spring IoC container that allow injecting all registered implementations of an interface into a list:
interface Foo {}
#Component
class FooImpl1 implements Foo {}
#Component
class FooImpl2 implements Foo {}
class Client {
#Autowired
List<Foo> allFoos;
}
Now you say:
While for factory pattern, the factory class creates the object on request. And it can create a new object for each request.
Actually Spring can create objects per request. Not all beans have to be singletons, in general spring has a concept of scopes for this purposes.
For example, scope prototype means that Spring will create a bean upon each usage. In particular one interesting usage that spring supports in variety of ways is Injecting prototype bean into singleton. Some solutions use exactly like a factory (read about annotation #Lookup others rely on auto-generated proxy in runtime (like javax.inject.Provider). Prototype scope beans are not held in the application context, so here again spring goes beyond a simple map abstraction.
Last feature that you haven't mentioned is that sometimes even for singletons the initialization can be a little bit more complicated then calling a constructor with Parameters. Spring can address that by using Java Configurations:
#Configuration
public class MyConfig {
public SomeComplicatedObject foo(#Value("...") config, Bar bar) {
SomeComplicatedObject obj = new SomeComplicatedObject() // lets pretend this object is from some thirdparty, it only has no-op constructor, and you can't place spring annotations on it (basically you can't change it):
obj.setConfig(config);
obj.setBar(bar);
return obj;
}
}
The method foo here initializes the object SomeComplicatedObject and returns it. This can be used instead of factories to integrate "legacy" code (well, java configurations go way beyond this, but its out of scope for this question).
So bottom line, you Spring as an IoC container can provide many different ways to deal with object creation, in particular it can do everything that factory design pattern offers.
Now, I would like to also refer to your last sentense:
I think a deeper question may be, when Spring framework is used in a project, should it be strived to not create any object inside a class, which means the factory pattern ( or any creational design patterns?) should not be used, as Spring is supposed to be the central handler of the objects dependency ?
Indeed you don't have to use Factory Pattern when using Spring, since (as I hopefully have convinced you) provides everything that factory can do and more.
Also I agree that spring is supposed to be the central handler of the objects dependency (unless there are also parts of the application which are written in a different manner so you have to support both :) )
I don't think we should avoid using "new" altogether, not everything should/can be a bean, but I do see (from my subjective experience, so this is arguable) that you use it much less leaving the creation of most of the objects to Spring.
Should we avoid a usage of any creation design pattern? I don't think so, sometimes you can opt for implementing "builder" design pattern for example, its also a creational pattern but spring doesn't provide a similar abstraction.
I think if your project uses Spring framework you should use it. Although it depends on your project design e.g. You may use creational patterns along side with Spring IoC. e.g when you have abstraction layers not framework dependant (agnostic code)
interface ServiceFactory {
Service create(String type);
}
#Component
class SpringServiceFactory implements ServiceFactory {
#Autowired private ApplicationContext context;
Service create(String type) {
return context.getBean(type)
}
}
I use Factory pattern as well when I refactor legacy not unit testable code which also uses Spring Framework in order to implement unit tests.
// legacy service impossible to mock
class LegacyApiClient implements Closeable {...}
#Component
class LegacyApiClientFactory {
LegacyApiClient create(String endpoint) {
return new LegacyApiClient(endpoint);
}
}
#Component
class OtherService {
private final String endpoint
private final LegacyApiClientFactory factory;
OtherService(#Value("${post.endpoint}") String endpoint,
LegacyApiClientFactory factory) {...}
void doCall {
try (LegacyApiClient client = factory.create(endpoint)) {
client.postSomething();
}
}
}
....
// a random unit test
LegacyApiClient client = mock(LegacyApiClient.class)
LegacyApiClientFactory factory = mock(LegacyApiClientFactory.class)
OtherService service = new OtherService("http://scxsc", factory);
when(factory.create(any())).thenReturn(client)
service.doCall()
....
I am trying to find a way how to programatically create bean in quarkus DI, but without success. Is it possible in this framework? It seems that BeanManager does not implement the needed method yet.
First, we should clarify what "programatically create bean" exactly means.
But first of all, we should define what "bean" means. In CDI, we talk about beans in two meanings:
Component metadata - this one describes the component attributes and how a component instance is created; the SPI is javax.enterprise.inject.spi.Bean
Component instance - the real instance used in application; in the spec we call it "contextual reference".
The metadata is usually derived from the application classes. Such metadata are "backed by a class". By "backed by a class" I mean all the kinds described in the spec. That is class beans, producer methods and producer fields.
Now, if you want to programatically obtain a component instance (option 2), you can:
Inject javax.enterprise.inject.Instance; see for example the Weld docs
Make use of CDI.current().select(Foo.class).get()
Make use of quarkus-specific Arc.container().instance(Foo.class).get()
However, if you want to add/register a component metadata that is not backed by a class (option 2), you need to add an extension that makes use of quarkus-specific SPIs, such as BeanRegistrar.
If you are looking for Quarkus equivalent of Spring #Configuration then you want "bean producer" (as mentioned in comments above)
Here is an example(koltin) of how to manually register a clock:
import java.time.Clock
import javax.enterprise.context.ApplicationScoped
import javax.enterprise.inject.Produces
#ApplicationScoped
class AppConfig {
#Produces
#ApplicationScoped
fun utcClock(): Clock {
return Clock.systemUTC()
}
}
#Produces is actually not required if method is already annotated with #ApplicationScoped
#ApplicationScoped at class level of AppConfig is also not required
Although, I find those extra annotations useful, especially if are used to Spring.
You can inject your beans using Instance:
#Inject
public TestExecutorService(final ManagedExecutor managedExecutor,
final Instance<YourTask> YourTask) {
this.managedExecutor = managedExecutor;
this.YourTask= YourTask;
}
And if you need to create more than one Instance you can use the managed executor:
tasks.forEach(task -> managedExecutor.submit(task::execute));
Keep in mind that depending on the way you start the bean you may need to destroy it and only the "creator class" has its reference, meaning you have to create and destroy the bean in the same classe (you can use something like events to handle that).
For more information please check: CDI Documentation
I implemented Dynamic DataSource Routing using Spring Boot (JavaConfig) to add and switch new DataSources in runtime.
I implemented AbstractRoutingDataSource and I need access to all resolvedDataSources that is a private property. How can I do it?
I actually don't know why that field has not been made protected to let implementing classes access the data sources set. Regarding your questions two options come into my mind.
Option 1:
Copy the code of AbstractRoutingDataSource into a class of your own. Then you can expose the resolvedDataSources simply by a getter. This should work as long as the configuration relies on the interface AbstractDataSource and not AbstractRoutingDataSource.
Option 2
Pick the brute force way by accessing the field via Reflection API
Do I use dependency injection in the following example:
#Scope("prototype")
#Component
public class Order{
#Autowired
public Order(User user,List<OrderItem> items,.......){
Now somewhere else:
#Component
public class PersistOrder{
#Autowired
Provider<Order> orderProvider;
public void prepareOrder() {
Order order = orderProvider.get();
AS JSR-330 states, the get() method of Provider returns a new instance of Order, but what objects are passed to the new order's constructor? As you can see the order has its own dependencies that has to be injected before the actual order object is retrieved to the method.
Without DI I simply create all neccessary arguments and pass them to the constructor of the new order. So should I use DI here?
EDIT:
This is what the code would seem without DI:
#Component
public class PersistOrder{
public void prepareOrder() {
User user=userDao.get(userId);
List<OrderItem> orderItems=orderItemDao.getAll(orderItemIds);
Order order = new SmartPhoneOrder(user,orderItems);
As you see I have the ids of user and order items and can get their instances from DAOs. Then I pass these instances to the constructor of a subclass of the Order to get an instance. The process seems very clear to me. I mean how can I do this work with DI so that my code enjoy decoupling between PersistOrder and Order classes? Or using DI in this example makes the logic more complex?
Without dependency injection, domain objects can be considered anaemic, and this is arguably an anti-pattern. You're losing many of the benefits of OO, by having data structures, without associated behaviors. For example, to evaluate Order.isValid() you may need to inject some dependency to perform the validation.
You can get dependency injection on classes outside the context of the Spring container by using:
#Configurable
You then declare the recipe for the bean as a protoype, and Spring will use AOP to swizzle the constructor and look up the required dependencies. . Even though its looking up the dependencies, the net effect for you is dependency injection, because you'd only have to change one line to inject something else that evaluates Order.isValid().
This way when you do new Order, or get it from you persistence factory, it already has the dependencies "injected".
To do this requires aspectJ weaving and not just Proxy/CGLib weaving, which is the default. You can use either runtime weaving with a Java agent or build-time weaving. . . I recommend the former for integration tests and the latter for deployment. . .
Service vs Domain Object:
Now that you have the option of rich domain objects the question becomes where to put stuff. Service vs Entity? My take is that the service should orchestrate a use-case specific process based on reusable domain objects. The service is your non-OO gateway for outside subscribers into you system.
. . Google Spring #Configurable for more information and tutorials on AspectJ-based dependency injection of domain classes.