Define a custom InjectionResolver for #Inject - jersey

My goal is to add some additional logic around the System Injection Resolver (to decorate it, so to speak). Basically, I want to register a custom injection resolver (e.g. described here), but for the javax.inject.#Inject Annotation. The setup works if I create a different custom annotation, but not when using #Inject. My implementation is as follows:
Injection Resolver:
#Singleton
#Rank(Integer.MAX_VALUE)
public class InjectInjectionResolver
implements InjectionResolver<Inject> {
private final InjectionResolver<Inject> injectionResolver;
#Inject
public InjectInjectionResolver(
#Named(InjectionResolver.SYSTEM_RESOLVER_NAME) final InjectionResolver<Inject> injectionResolver) {
this.injectionResolver = injectionResolver;
}
#Override
public Object resolve(final Injectee injectee, final ServiceHandle<?> root) {
throw new RuntimeException("Why is this never called?");
}
#Override
public boolean isConstructorParameterIndicator() {
return injectionResolver.isConstructorParameterIndicator();
}
#Override
public boolean isMethodParameterIndicator() {
return injectionResolver.isMethodParameterIndicator();
}
}
And I register the resolver as follows (inside ResourceConfig):
register(new AbstractBinder() {
#Override
protected void configure() {
bind(InjectInjectionResolver.class).to(new GenericType<InjectionResolver<Inject>>() {}).in(Singleton.class);
}
});
What I tried so far:
using #Rank
using both the org.glassfish.jersey.internal.inject.AbstractBinder or org.glassfish.hk2.utilities.binding.AbstractBinder with TypeLiteral, along with implementing the org.glassfish.hk2.api.InjectionResolver or org.glassfish.jersey.internal.inject.InjectionResolver
making sure the same setup works with #CustomAnnotation (where both the constructor and the resolve methods are called)
Does anyone know how to solve this issue?
Versions used: jersey 2.27
EDIT: When I #Inject the InjectionResolver itself, it seems that hk2's org.jvnet.hk2.internal.ThreeThirtyResolver is injected for the org.glassfish.hk2.api.InjectionResolver, while my custom injection resolver is injected for org.glassfish.jersey.internal.inject.InjectionResolver. However, the custom injection resolver is not used for injection.

The following configuration works for me, thanks to #jwells131313 for bringing me back on track. I tried to use fully qualified names, else it's probably from the javax.inject.* package.
#Singleton
#Rank(Integer.MAX_VALUE)
#org.jvnet.hk2.annotations.Service
public class MyHk2InjectionResolver
implements org.glassfish.hk2.api.InjectionResolver<Inject> {
private final org.glassfish.hk2.api.InjectionResolver<Inject> injectionResolver;
#Inject
public MyHk2InjectionResolver(
#Named(org.glassfish.hk2.api.InjectionResolver.SYSTEM_RESOLVER_NAME) final org.glassfish.hk2.api.InjectionResolver<Inject> injectionResolver) {
this.injectionResolver = injectionResolver;
}
// ... required methods, could just delegate to system resolver
}
To register the resolver, we bind it to the correct type (I do it in the ResourceConfig of a jersey application):
register(new org.glassfish.hk2.utilities.binding.AbstractBinder() {
#Override
protected void configure() {
bind(MyHk2InjectionResolver.class)
.to(new org.glassfish.hk2.api.TypeLiteral<org.glassfish.hk2.api.InjectionResolver<Inject>>() {})
.in(Singleton.class);
}
});
With this setup, you can keep using the #Inject annotation and write some custom injection logic around it, possibly using the default system injection resolver as a fallback.

Related

Field injection works but constructor injection returns NullPointerException

While looking at an existing Spring application, I stumbled upon a class with field injection, which we all know isn't recommended for various reasons. I have then decided to refactor it to make use of a more appropriate approach: constructor based DI.
Before refactoring
#Component
public class MaintenanceModeInterceptor implements HandlerInterceptor {
private static final String MAINTENANCE_MODE_VIEW = "common/maintenanceMode";
#Autowired
private ApplicationObject applicationObject;
public MaintenanceModeInterceptor() {
// Required by Spring
}
...
}
After refactoring
#Component
public class MaintenanceModeInterceptor implements HandlerInterceptor {
private static final String MAINTENANCE_MODE_VIEW = "common/maintenanceMode";
private ApplicationObject applicationObject;
public MaintenanceModeInterceptor() {
// Required by Spring
}
#Autowired
public MaintenanceModeInterceptor(ApplicationObject applicationObject) {
this.applicationObject = applicationObject;
}
...
}
Maybe it is related to the fact that a default constructor is present. However, if I remove it, I end up having this exception:
Caused by: java.lang.NoSuchMethodError: my.application.web.interceptor.MaintenanceModeInterceptor: method <init>()V not found
So my understanding is that Spring requires a default constructor for interceptors.
Is there any way to achieve construtor based DI in this scenario?
Thank you.
I think you should remove the non #Autowired constructor and do perform a clean build on your project.

Spring Zuul: Dynamically disable a route to a service

I'm trying to disable a Zuul route to a microservice registered with Eureka at runtime (I'm using spring boot).
This is an example:
localhost/hello
localhost/world
Those two are the registered microservices. I would like to disable the route to one of them at runtime without shutting it down.
Is there a way to do this?
Thank you,
Nano
Alternatively to using Cloud Config, custom ZuulFilter can be used. Something like (partial implementation to show the concept):
public class BlackListFilter extends ZuulFilter {
#Override
public String filterType() {
return "pre";
}
...
#Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
String uri = ctx.getRequest().getRequestURI();
String appId = uri.split("/")[1];
if (blackList.contains(appId)) {
ctx.setSendZuulResponse(false);
LOG.info("Request '{}' from {}:{} is blocked",
uri, ctx.getRequest().getRemoteHost(), ctx.getRequest().getRemotePort());
}
return null;
}
}
where blackList contains list of application IDs (Spring Boot application name) managed for example via some RESTful API.
After a lot of efforts I came up with this solution. First, I used Netflix Archaius to watch a property file. Then I proceeded as follows:
public class ApplicationRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {
public ApplicationRouteLocator(String servletPath, ZuulProperties properties) {
super(servletPath, properties );
}
#Override
public void refresh() {
doRefresh();
}
}
Made the doRefresh() method public by extending SimpleRouteLocator and calling its method in the overridden one of the interface RefreshableRouteLocator.
Then I redefined the bean RouteLocator with my custom implementation:
#Configuration
#EnableConfigurationProperties( { ZuulProperties.class } )
public class ZuulConfig {
public static ApplicationRouteLocator simpleRouteLocator;
#Autowired
private ZuulProperties zuulProperties;
#Autowired
private ServerProperties server;
#Bean
#Primary
public RouteLocator routeLocator() {
logger.info( "zuulProperties are: {}", zuulProperties );
simpleRouteLocator = new ApplicationRouteLocator( this.server.getServletPrefix(),
this.zuulProperties );
ConfigurationManager.getConfigInstance().addConfigurationListener( configurationListener );
return simpleRouteLocator;
}
private ConfigurationListener configurationListener =
new ConfigurationListener() {
#Override
public void configurationChanged( ConfigurationEvent ce ) {
// zuulProperties.getRoutes() do something
// zuulProperties.getIgnoredPatterns() do something
simpleRouteLocator.refresh();
}
}
}
Every time a property in the file was modified an event was triggered and the ConfigurationEvent was able to deal with it (getPropertyName() and getPropertyValue() to extract data from the event). Since I also Autowired the ZuulProperties I was able to get access to it. With the right rule I could find whether the property of Zuul
zuul.ignoredPatterns
was modified changing its value in the ZuulProperties accordingly.
Here refresh context should work (as long as you are not adding a new routing rule or removing a currently existing one), if you are adding or removing routing rules, you have to add a new bean for ZuulProperties and mark it with #RefreshScope, #Primary.
You can autowire refreshEndpoint bean for example and apply refreshEndpoint.refresh() on the listener.
Marking a custom RouteLocator as primary will cause problems as zuul already has bean of same type marked as primary.

Java 8 and Spring 4 : Use autowiring in interface

Java 8 added a new feature by which we can provide method implementation in interfaces.
Is there any way in Spring 4 by which we can inject beans in the interface which can be used inside the method body?
Below is the sample code
public interface TestWiring{
#Autowired
public Service service;// this is not possible as it would be static.
//Is there any way I can inject any service bean which can be used inside testWiringMethod.
default void testWiringMethod(){
// Call method of service
service.testService();
}
}
This is a bit tricky but it works if you need the dependency inside the interface for whatever requirement.
The idea would be to declare a method that will force the implemented class to provide that dependency you want to autowire.
The bad side of this approach is that if you want to provide too many dependencies the code won't be pretty since you will need one getter for each dependency.
public interface TestWiring {
public Service getService();
default void testWiringMethod(){
getService().testService();
}
}
public class TestClass implements TestWiring {
#Autowire private Service service;
#Override
public Service getService() {
return service;
}
}
You can created Class utils of application context and use it everywhere even not bean class .
you can have code somethins this :
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext context) {
ApplicationContextUtil.applicationContext = context;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}
and add this to your spring configuration
<bean class="com.example.ApplicationContextUtil" id="applicationContextUtil"/>
now simple to use when you need :
ApplicationContextUtil.getApplicationContext().getBean(SampleBean.class)
this word in web and simple spring app.

Spring Autowiring not working for Abstract classes

I have a project where I have an interface, an Abstract class implementing the same interface and then a set of concrete classes which implement this interface and extend the Abstract Class.
public interface Invoice
{
void process();
}
#component
public abstract class AbstractInvoice(){
#Resource
protected Writer writer;
protected validateInvoice(){
//some implementation
}
}
#Component
public Class TypeAInvoice() extends AbstractInvoice implements Invoice{
#Override
public void process(){
//... some code
writer.write();
}
}
public Interface Writer(){
public void write();
}
#Component
public class CDWriter implements Writer{
#Override
public void write() { /* implementation.....*/}
}
Spring file has a component scan for the package.
<context:annotation-config>
<context:component-scan base-package="com.xyz" />
I am using a factory to get an instance of TypeAInvoice invoice
Now calling invoice.process() gets a NPE when getting to write.write()
I am not sure what am I missing here. I tried to see the component scan and scope and could not find anything conceptually wrong.
I am using a factory to get an instance of TypeAInvoice invoice
Depending on what your Factory does, this may be the problem. If the Factory creates a new TypeAInvoice, Spring wiring doesn't apply. You have to query the Spring context for the Bean. One way (though not very pretty) is to use ContextLoader:
return ContextLoader.getCurrentWebApplicationContext().getBean(TypeAInvoice.class)
I'd say static Factories and Spring don't go to well together. Spring stands for the Inversion of Control pattern, while Factories stand for the Service Locator pattern. I'd suggest that you get rid of your factories and autowire your Spring Beans.
Everything is good, except for the fact you use a factory to get the TypeAInvoice. If you create it like TypeAInvoice typer = new TypeAInvoice() then spring knows nothing of it, the Writer is not autowired, there for you get the NullPointerException. You should get the bean from the spring application context.
In my case, inside a Spring4 Application, i had to use a classic Abstract Factory Pattern(for which i took the idea from - http://java-design-patterns.com/patterns/abstract-factory/) to create instances each and every time there was a operation to be done.So my code was to be designed like:
public abstract class EO {
#Autowired
protected SmsNotificationService smsNotificationService;
#Autowired
protected SendEmailService sendEmailService;
...
protected abstract void executeOperation(GenericMessage gMessage);
}
public final class OperationsExecutor {
public enum OperationsType {
ENROLL, CAMPAIGN
}
private OperationsExecutor() {
}
public static Object delegateOperation(OperationsType type, Object obj)
{
switch(type) {
case ENROLL:
if (obj == null) {
return new EnrollOperation();
}
return EnrollOperation.validateRequestParams(obj);
case CAMPAIGN:
if (obj == null) {
return new CampaignOperation();
}
return CampaignOperation.validateRequestParams(obj);
default:
throw new IllegalArgumentException("OperationsType not supported.");
}
}
}
#Configurable(dependencyCheck = true)
public class CampaignOperation extends EO {
#Override
public void executeOperation(GenericMessage genericMessage) {
LOGGER.info("This is CAMPAIGN Operation: " + genericMessage);
}
}
Initially to inject the dependencies in the abstract class I tried all stereotype annotations like #Component, #Service etc but even though Spring context file had ComponentScanning for the entire package, but somehow while creating instances of Subclasses like CampaignOperation, the Super Abstract class EO was having null for its properties as spring was unable to recognize and inject its dependencies.After much trial and error I used this **#Configurable(dependencyCheck = true)** annotation and finally Spring was able to inject the dependencies and I was able to use the properties in the subclass without cluttering them with too many properties.
<context:annotation-config />
<context:component-scan base-package="com.xyz" />
I also tried these other references to find a solution:
http://www.captaindebug.com/2011/06/implementing-springs-factorybean.html#.WqF5pJPwaAN
http://forum.spring.io/forum/spring-projects/container/46815-problem-with-autowired-in-abstract-class
https://github.com/cavallefano/Abstract-Factory-Pattern-Spring-Annotation
http://www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring
https://www.madbit.org/blog/programming/1074/1074/#sthash.XEJXdIR5.dpbs
Using abstract factory with Spring framework
Spring and Abstract class - injecting properties in abstract classes
Inject spring dependency in abstract super class
Spring autowire dependency defined in an abstract class
Spring can you autowire inside an abstract class?
Please try using **#Configurable(dependencyCheck = true)** and update this post, I might try helping you if you face any problems.
So precisely my point here is you don't need to get a bean from spring context all the time.

How to use #Autowired to dynamically inject implementation like a factory pattern

I am fairly new to Sprint and am using Spring 3.x and roo1.1.1 for my application.
I have multiple implementation of an interface which would be #Autowired into other different classes. I would only be able to decide which implementation to go with at the runtime. This should be achieved with like a factory pattern.
public interface SomeInterface {
public void doSomething();
}
Implementation 1.
public class SomeOb implements SomeInterface {
public void doSomething() {
//Do something for first implementation here
}
}
Implementation 2.
public class SomeOtherOb implements SomeInterface {
public void doSomething() {
//Do something for first implementation here
}
}
Now in my service i needed this Autowired like
#Service
public class MyService {
#Autowired
SomeInterface ob;
//Rest of the code here
}
1) The logic to choose which implementation to be Autowired is only know runtime, so i cannot use the #Qualifier annotation to qualify this.
2) I tried to create a FactoryBean like
public class SomeFactoryBean implements FactoryBean<SomeInterface> {
#Override
public SomeInterface getObject() throws Exception {
if(/*Somecondition*/) {
return new SomeOb();
} else
return new SomeOtherOb();
}
#Override
public Class<? extends SomeInterface> getObjectType() {
if(/*Somecondition*/) {
return SomeOb.class;
} else
return SomeOtherOb.class;
}
#Override
public boolean isSingleton() {
return false;
}
}
In the applicationContext.xml i have the tag mentioned.
When i run the webserver i run into an error like
No unique bean of type [com.xxxx.xxxx.SomeInterface] is defined: expected single matching bean but found 3: [xxxx, xxxxxxx, xxxxFactory]
Can anyone please help me to resolve this issue. If i am not doing this right please direct me to do this the right way.
Thanks and appreciate any help,
jjk
Thanks for the suggestion. I was able to solve the problem with help from a colleague. What i was doing wrong
I had the implementation of the SomeInterface with #Service. So this was picked up by the spring scanner and added to the bean.
During trial and error i removed the #Component annotation from by FactoryBean implementation.
After making these changes it worked like a charm.
return true from isSingleton() if you only need one implementation of the bean for a given instance of your application
But I question your design.
I would always use properties files to switch out implementations like this. I once had to implement CAPTCHA integration for a site. We were prototyping with the JCaptcah and ReCAPTCHA APIs. I created a new interface that contained just the functionality we needed and then created implementations for both APIs. Using a placeholders in the Spring configuration file and Maven profiles, we could switch out the implementation class at compile time or deployment time, for example, mvn jetty:run -DcaptchaImpl=recaptcha or -DcaptchaImpl=jcaptcha.
Without knowing the task that you want to accomplish, it's hard to provide more advice.

Resources