I'd like to write some base classes that should be picked by default to autowire with Spring. Only if these classes are extended, thus a custom implementation is provided for them, I want the custom implementation to be picked up, instead of the default one.
How can I achieve it when I don't want to make my default classes abstract (as the application should be able to run without custom implementations, just by the default ones)?
The the following example: I want to provide a basic handler for any errors. But this setup would only work if I make the BaseHandler abstract, which I don't want (as in this case I would force anyone using my library to implement the class).
#MessageEndpoint
public class BaseHandler {
#ServiceActivator(inputChannel = "errorChannel")
public A_Stadisdatensatz handle(Message<MessageHandlingException> message) {
process(message.getPayload());
}
/**
* Override to supply specific processing
*/
void process(Payload payload) {
//do some default processing
}
}
#MessageEndpoint
public class CustomHandler extends BaseHandler {
#Override
void process(Payload payload) {
//custom processing
}
}
If I run it this way, CustomHandler will never be picked up.
So, is it impossible?
I supose that you are using #Autowired to inject the dependencies. In that case you could use #Primary annotation to override defaults ones, ie
#Primary
#MessageEndpoint
public class CustomHandler extends BaseHandler {
#Override
void process(Payload payload) {
//custom processing
}
}
Related
Simplified example to give you an idea, hope it's be clear.
I've already added inheritance for Service class to avoid switches I'm having now
class Config {}
class ConfigA extends Config {}
class ConfigB extends Config {}
// service class - different implementation for configA and ConfigB
// normally it would look like
class ServiceA {
public String run(ConfigA configA) {}
}
thus next then I need sth like
class ServiceRunner {
public String run(Config config) {
// if or switch doesn't matter now
if (config instanceof ConfigA) {
return serviceA.run((ConfigA)config);
}
}
}
// main
Config config = configFactory.create(...) // returns ConfigA or ConfigB
String result = serviceRunner.run(config);
Is there a better way to code it I mean without casting?
The only solution I can see is:
interface Service { String run(); }
#RequestScope
class ServiceA implements Service {
private ConfigA config;
public ServiceA(ConfigA configA) {this.configA = configA}
public String run() {
...
}
}
but I'm not convinced it's a good idea to implement service beans as state beans and I'm using CDI (quarkus actually) for DI which it seems doesn't support assisted injection via constructor
Why don't you hide the detail about which Config a given Service handles inside the Service itself? By doing so you could have something like the following:
interface Service {
boolean handlesConfig(Config config)
String run(Config config);
}
class ServiceRunner {
private List<Service> services;
public String run(Config config) {
for (service : services) {
if (service.handles(config)) {
return service.run(config);
}
}
}
}
Seems like it's a case for Bridge pattern. You have parallel hierarchies of service and config. So if tomorrow there is a ServiceC, there would supposedly be a ConfigC. There might be an abstraction which is common in both service and config. Try to find it and abstract it out. Then service would be using that abstraction. And ConfigA, ConfigB would be impls of that abstraction.
Or perhaps, as the replier above mentioned, service should be programmed to the abstract config instead of impls.
Does the Configs have different types of interfaces that can't be extracted into a common interface? In that case, it is violating the Liskov's substitution principle, which requires that all subclasses should be interchangeable. e.g. the hierarchy of Shape <- Rectangle <- Square is wrong, because square is not a type of rectangle (programmatically, of course) - because Rectangle has 2 dimensions, namely length and breadth, while square has one dimension of length only. Making this hierarchy would break the abstraction. Similarly, it might be your case that the hierarchy of Config may not be a hierarchy at all.
I would like to write a JUnit5 Extension that extends my test class,
#ExtendWith(MyExtension.class)
public class MyTestClass {
#Test myTest1() {}
#Test myTest2() {}
// ...
}
However, my test class also implements a certain interface, so it looks more like this:
public interface SomeInterface {
SomeClient getSomeClient();
SomeClient getSomeClientAsAdministrator();
}
#ExtendWith(MyExtension.class)
public class MyTestClass implements SomeInterface {
#Test myTest1() {}
#Test myTest2() {}
// ...
SomeClient getSomeClient() {
// ...
}
SomeClient getSomeClientAsAdministrator() {
// ...
}
}
No mysteries so far.
But now, I want those interface implementations to be available to the extension as well, e.g.
public class MyExtension implements BeforeEachCallback, SomeInterface
{
#Override
public void beforeAll(ExtensionContext extensionContext) {
// be able to use getSomeClient();
}
}
How can I set up my classes to achieve this? (Or, what is the inherent flaw or code smell against doing this?)
You need to use the #RegisterExtension annotation which allows you to construct your extension instance manually.
When an extension is registered declaratively via #ExtendWith, it can
typically only be configured via annotations. In contrast, when an
extension is registered via #RegisterExtension, it can be configured
programmatically — for example, in order to pass arguments to the
extension’s constructor, a static factory method, or a builder API.
It sounds like SomeClient is provided from elsewhere (a DI like Spring perhaps) but you need it in MyExtension. Assuming this scenario, you can start with something like:
#ExtendWith(SpringExtension.class)
public class MyTestClass {
#Autowired SomeClient someClient;
#RegisterExtension
MyExtension myExtension = new MyExtension(someClient);
}
One way to achieve that is to use getTestInstance() on the context object:
public class MyExtension implements BeforeEachCallback {
#Override
public void beforeEach(ExtensionContext context) throws Exception {
context.getTestInstance().ifPresent(instance -> {
if (instance instanceof SomeInterface) {
SomeInterface some = (SomeInterface) instance;
System.out.println(some.getSomeClient());
}
});
}
}
What you can see here is two things:
There might not be a test instance object, e.g. in a BeforeAllCallback because test instances are usually created per test.
A cast is required. That means you should check if your test instance really does implement SomeInterface
Having said that, I'm not really sure why you'd want to go down that rather complicated route. What's MyExtension supposed to abstract from?
Hallo i would like to find a way to elect programmatically a Candidate between different implementation present on the bean factory, at Spring Container Level.
With Profiles i can achieve that simply like this
I Have the following Profiles "CH" and "IT" and i want that if a Bean Profiled with IT is there, then will fallback to default.
Given those classes:
The Default Implementation
#Component
public class DefaultMapper {
public void doSomething() {
System.out.println("Map Default");
}
}
The Swiss Implementation
#Component
#Profile("CH")
public class SwissMapper extends DefaultMapper {
#Override
public void doSomething() {
System.out.println("do something swiss");
}
}
The Italian Implementation:
#Component
#Profile("IT")
public class ItalianMapper extends DefaultMapper {
#Override
public void doSomething() {
System.out.println("do pasta");
}
}
Now if i run it with #ActiveProfiles("IT") it throws a NoUniqueBeanDefinitionException, which is fair enough, since the Default is not profiled, and it will be registered without any further attention by the container.
Some Consideration:
if i add #Profile("default") to DefaultMapper this will work until i have another default bean has a subclass profiled ONLY with CH.
Default Implementation of another Bean:
#Component
#Profile("default")
public class DefaultParser {
public void doSomething() {
System.out.println("Parse Default");
}
}
Then the Swiss implementation (No italian is available, or better said the default fits for italian):
#Component
#Profile("CH")
public class SwissParser extends DefaultParser {
#Override
public void doSomething() {
System.out.println("Ässe Ässe");
}
}
Now if i run it with #ActiveProfiles("IT") it throws a No BeanDefinitionException, which is fair enough, but not that fair, since the "default" is not chained as ActiveProfiles and for IT i have no implementation. the CH profile here will work since has a profiled implementation for each default class.
Said That
I would like a better way to cover this scenario without:
- Having to define on the Default Classes such #Profile({"default","IT", "<all other profiles which have NOT a specialized implementation"} , or #Profile("!CH") where i exclude those profiles which have a specialization.
- #Primary i think is not a soultion, because on the DefaultMapper i have to Specialization which will be marked as #Primary and the container doesn't like it at all ;)
Then
I would like to solve this where i can decide for ALL the injected Classes, when the resolution of the Beans is ambigous then i would like to programmatically decide (in container) which implementation i would like to pick. I think an Annotation likewise to #Profile , i.E #Candidate("CH") will suit compared to a value set in application.properties in a i.E nationality.cantidate=CH. Something like:
public class MyExtension extends UnknowSpringType {
#Override
Object resolveAmbigousDependency(final Context ctx, final Resolution resolution) {
final List<Class> clazzes = resolution.getResolvedClasses();
for (final Class clazz : clazzes) {
if (clazz.isAnnotationPresent(Candidate.class) && clazz.getAnnotation(Candidate.class).getVaue().equals(candidateApplicationPropertyValue)) {
return clazz;
}
return getDefaultImplementation(clazzes);
}
}
I've done in the past Something similar with CDI SPI extension wich is elegant, and also i could cover this in another way with #Specializes from CDI, but i cannot find the same easy way on Spring (i don't have so much experience on it), BeanFactory? BeanFactoryPostProcessor ?
Help ?
You can mark all your specific Parsers as #Primary this will make sure Spring autowires this one instead of the default one which is not marked as #Primary. When no specific Parsers exist for the chosen profile it will fall back to the non #Primary default component.
See: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Primary.html
#Component
public class DefaultParser {
public void doSomething() {
System.out.println("Parse Default");
}
}
#Component
#Primary
#Profile("CH")
public class SwissParser extends DefaultParser {
#Override
public void doSomething() {
System.out.println("Ässe Ässe");
}
You can activate multiple profiles, CH and IT and your implementation will fail.
It is a internationalization problem.
I provide a Spring statemachine with basic program states in a library
as base for different implementations. Adding custom transition actions depending on the current implementation using the basic statemachine, seems to be easy because of the provided transition annotations.
Now I want to do something similar with guards, i.e. provide a transition guard depending on the recent usage scenario within the implementation using the basic statemachine.
One idea is to configure a default guard within the basic statemachine which is implementing the decorator pattern, i.e. it is a wrapper implementing the guard interface wrapped around another guard. As default guard wrapped a simple guard implementation is used which always returns true for
the evaluate method.
Code snippets look something like ... first the guards:
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.guard.Guard;
// ... custom States and Events imports
public class GuardDecorator implements Guard<States, Events> {
private Guard<States, Events> guard;
public GuardDecorator() {
this.guard = new DefaultGuard();
}
public GuardDecorator(Guard<States, Events> guard) {
this.guard = guard;
}
public void setGuard(Guard<States, Events> guard) {
this.guard = guard;
}
public String wrappedGuardInfo() {
return this.guard.toString();
}
#Override
public boolean evaluate(StateContext<States, Events> context) {
return this.guard.evaluate(context);
}
}
public class DefaultGuard implements Guard<States, Events> {
#Override
public boolean evaluate(StateContext<States, Events> context) {
return true;
}
}
Now using the GuardDecorator in the statemachine Configurer (excerpt only):
// ...
#Bean
public GuardDecorator guard() {
return new GuardDecorator();
}
// ...
#Override
public void configure(
StateMachineTransitionConfigurer<States, Events> transitions)
throws Exception {
transitions.withExternal()
.source(States.S1)
.target(States.S2)
.event(Events.E1)
.guard(guard());
}
// ...
My questions are now:
Did I miss something in the documentation, is there a build-in way to do this?
Any other solutions to get an implementation dependend guard for a basic
statemachine provided within a library?
There's nothing build-in but not sure if there has to be. If you do this config based on JavaConfig, you could create default guard there and allow user to autowire optional overridden implementation
Autowired(required=false)
#Qualifier("myGuard")
Guard<States, Events> guard;
Or allowing user to override bean definition itself. If same bean is created in multiple configuration classes, latest resolved in order wins. This concept is used heavily in Spring Umbrella projects where default bean exists but is allowed to be overridden by a user.
#Bean(name="myGuard")
public GuardDecorator guard() {
return new GuardDecorator();
}
Is there a way to declare default binding in Guice 3.0 ?
Here is an example of what I expected :
//Constructor for Class Impl1
#Inject
public Impl1 (#One IMyOwn own)
{
...
}
//Constructor for Class Impl2
#Inject
public Impl2 (#Two IMyOwn own)
{
...
}
//Declare a default binding
bind(IMyOwn.class).to(DefaultMyOwn.class);
//Then, if I want to bind a custom implementation for #Two
bind(IMyOwn.class).annotatedWith(Two.class).to(TwoMyOwn.class);
Actually, this example can't works because I must declare a binding for all annotation (#One, #Two).
Are there solutions to do that with Guice ?
Thanks.
Use the #Named binding.
From Guice Reference on Github:
Guice comes with a built-in binding annotation #Named that uses a string:
public class RealBillingService implements BillingService {
#Inject
public RealBillingService(#Named("Checkout") CreditCardProcessor processor) {
...
}
To bind a specific name, use Names.named() to create an instance to pass to annotatedWith:
bind(CreditCardProcessor.class)
.annotatedWith(Names.named("Checkout"))
.to(CheckoutCreditCardProcessor.class);
So in your case,
//Constructor for Class Impl1
#Inject
public Impl1 (#Named("One") IMyOwn own)
{
...
}
//Constructor for Class Impl2
#Inject
public Impl2 (#Named("Two") IMyOwn own)
{
...
}
and your module will look like:
public class MyOwnModule extends AbstractModule {
#Override
protected void configure() {
bind(IMyOwn.class)
.annotatedWith(Names.named("One"))
.to(DefaultMyOwn.class);
bind(IMyOwn.class)
.annotatedWith(Names.named("Two"))
.to(TwoMyOwn.class);
}
}
With Guice 4.X there is Optional Binder.
public class FrameworkModule extends AbstractModule {
protected void configure() {
OptionalBinder.newOptionalBinder(binder(), Renamer.class);
}
}
public class FrameworkModule extends AbstractModule {
protected void configure() {
OptionalBinder.newOptionalBinder(
binder(),
Key.get(String.class, LookupUrl.class))
.setDefault().toInstance(DEFAULT_LOOKUP_URL);
}
}
In Guice 3.0 you may be able to exploit the automatic binding of the default constructor.
Use a single #Inject or public no-arguments constructor.
But this has constraints, as your default constructor needs to be of the same concrete class so derivation may become cumbersome.
Guice tries to check as much of your configuration (aka. Binding) as possible. This also means, that Guice cannot tell whether a missing binding for #One is an error or should map to some default case.
If you are interested in the details, lookup the BindingResolution sequence in Guice. Since step 4 and step 6 deal with binding annotation and step 6 explicitly forbids default, I think you are out of luck.
.6. If the dependency has a binding annotation, give up. Guice will not create default bindings for annotated dependencies.
So the best you can do is to provide Guice with a hint, that #One should map to the default like this:
bind(IMyOwn.class).annotatedWith(One.class).to(IMyOwn.class);
So you do not need to state the concrete default class DefaultMyOwn multiple times.