I use java 8 SE and jersey. I found example of jwt service here,
there is used java 6 EE.
Does someone know about analogs of this annotations or other solution of this problem?
I solved it by replacing this annotations on #Singelton and adding
ApplicationBinder
public class ApplicationBinder extends AbstractBinder {
#Override
protected void configure() {
bind(UserService.class).to(UserService.class).in(Singleton.class);
}
}
ResourceConfig
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
register(new ApplicationBinder());
packages(true, "api");
}
}
than I just can inject bean-classes by annotation #Inject
Related
I migrate the code to springboot and our API works well. Only interceptor can't be triggerred.
I googled related solutions and modify the code to right format which still failed to trigger the interceptor.
In our project, we also have the filter which extends OncePerRequestFilter and works.
It makes me confused.
They should be no big difference.
Btw, AOP is used in the project.
It's my code.
JerseyConfig.class
#Configuration
public class JerseyConfig extends ResourceConfig {
public JerseyConfig(){
packages("com.xxx");
}
}
VaultAuthorizationInterceptor.class
#Component
public class VaultAuthorizationInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(VaultAuthorizationInterceptor.class);
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("test");
return true;
}
}
VaultAuthConfig.class
#Configuration
public class VaultAuthConfig implements WebMvcConfigurer {
#Bean
public VaultAuthorizationInterceptor getVaultInterceptor() {
return new VaultAuthorizationInterceptor();
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getVaultInterceptor()).addPathPatterns("/**");
}
}
When you are using the spring-boot-starter-jersey, you use jersey as your web stack. That means any requests will processed by jersey. So you have to register a jersey filter or interceptor. Take a look at the jersey documantation. There is described how to use filters and interceptors. I think you want to use a filter because interceptors in the jersey stack used to manipulate the input or output stream.
This is my jersey config class
#ApplicationPath("services")
public class JerseyApplication extends ResourceConfig{
public JerseyApplication() {
packages("com.ems");
register(EmployeeService.class);
}
}
Here autowiring of employeeService is giving a null pointer exception
#Path("/ems")
#Component
public class EmployeeRestController {
#Autowired
private EmployeeService employeeService;
#GET
#Path("/employees")
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public List<Employee> getEmployees() {
return employeeService.getEmployees();
}
}
I have tried everything
In my employeeServiceImpl I have #service annotation
Still, it is not working.
To configure the dependency injection using the built in DI framework (HK2), you should use an AbstractBinder, as mentioned in some answers in Dependency injection with Jersey 2.0.
#ApplicationPath("services")
public class JerseyApplication extends ResourceConfig {
public JerseyApplication() {
packages("com.ems");
register(new AbstractBinder() {
#Override
protected void configure() {
bind(EmployeeService.class)
.to(EmployeeService.class)
.in(Singleton.class);
}
});
}
}
Secondly, you do not use the #Autowired annotation. This annotation is specifically for Spring. For standard injection with Jersey, just use the #Inject annotation. Also remove the #Component annotation, as this is also for Spring.
As an aside, if you do want to integrate Spring with Jersey, you should read Why and How to Use Spring With Jersey. It will break down what you need to understand about integrating the two frameworks.
You should register Controller not Service class.
Sample
#ApplicationPath("services")
public class JerseyApplication extends ResourceConfig{
public JerseyApplication() {
packages("com.ems");
register(EmployeeRestController.class);
}
}
I need to extend the WebMvcConfigurationSupport class too modify two things:
#Configuration
public class WebConfig extends WebMvcConfigurationSupport {
#Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping();
handlerMapping.setRemoveSemicolonContent(false);
handlerMapping.setOrder(1);
return handlerMapping;
}
}
I like the defaults that are registered from the WebMvcAutoConfiguration class but due to the conditional annotation on the class, when I extend the WebMvcConfigurationSupport class it prevents the auto configuration from happening.
#Configuration
#ConditionalOnWebApplication
#ConditionalOnClass({ Servlet.class, DispatcherServlet.class,
WebMvcConfigurerAdapter.class })
#ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
#Order(Ordered.HIGHEST_PRECEDENCE + 10)
#AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
public class WebMvcAutoConfiguration {...}
Is there to have the WebMvcAutoConfiguration class load without having to essentially copy/paste most of the code in that class?
Or is it possible to call RequestMappingHandlerMapping setOrder() and setRemoveSemicolonContent() from somewhere else so I can just use the #EnableWebMvc annotation and have the autoconfiguration class run without any issues?
Thanks in advance!
Extend from DelegatingWebMvcConfiguration instead of WebMvcConfigurationSupport, it will not prevent the autoconfig to take place:
#Configuration
public class WebConfig extends DelegatingWebMvcConfiguration {
#Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping();
handlerMapping.setRemoveSemicolonContent(false);
handlerMapping.setOrder(1);
return handlerMapping;
}
}
I managed to customize the RequestMappingHandlerMapping while keeping WebMvcAutoConfiguration using a BeanPostProcessor:
#Configuration
public class RequestMappingConfiguration {
#Bean
public RequestMappingHandlerMappingPostProcessor requestMappingHandlerMappingPostProcessor() {
return new RequestMappingHandlerMappingPostProcessor();
}
public static class RequestMappingHandlerMappingPostProcessor implements BeanPostProcessor {
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof RequestMappingHandlerMapping) {
((RequestMappingHandlerMapping) bean).setUseSuffixPatternMatch(false);
}
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
}
I would be happy if Spring Boot provides a better way to handle that... maybe something could be done around PathMatchConfigurer ?
Your analysis is correct (#EnableWebMvc or directly extending WebMvcConfigurationSupport will switch off the WebMvcAutoConfiguration). I'm not sure what the alternative is, since a) we need a "get-out" clause for the autoconfig, and b) I don't think Spring likes to have two WebMvcConfigurationSupports in the same context. Happy to discuss on github if you want to try and find a way to change it (there might be some middle ground).
I think the best way to do this in Spring Boot now is to add a WebMvcRegistrations component to your context - this solution didn't exist at the time of your question (it's been available since Spring Boot 1.4.0).
I would like to create a class whose objects can be injected using the #Context annotation (or better yet a custom annotation for cases where I need to pass an argument to the annotation) into resource methods. In Jersey 1.* I would have used InjectableProvider (in my case together with AbstractHttpContextInjectable). What I'm trying to achieve is something like #Auth [1] from dropwizard (which uses Jersey 1.7).
The injection capabilities of Jersey were replaced by HK2 as far as I know and I could not find any example of what I'm describing.
Edit: See this question for further problems I have encountered while trying to follow Michal's guide.
You need to implement InjectionResolver<T> interface from HK2. Take a look at existing implementations that are present in Jersey workspace:
ContextInjectionResolver handling #Context
ParamInjectionResolver handling #PathParam, #QueryParam, ... (via it's subclasses)
AutowiredInjectResolver handling #Autowired
Once you have this, you need to extend AbstractBinder from HK2 and bind your InjectionResolver via it's #configure() method:
public class MyResolverBinder extends AbstractBinder {
#Override
protected void configure() {
bind(MyInjectionResolver.class)
.to(new TypeLiteral<InjectionResolver<MyAnnotation>>() {})
.in(Singleton.class);
}
}
... and register an instance of this binder in your application class (or via feature):
Feature:
public class MyFeature implements Feature {
#Override
public boolean configure(final FeatureContext context) {
context.register(new MyResolverBinder());
return true;
}
}
register MyFeature into Application:
public class JaxRsApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
final HashSet<Class<?>> classes = new HashSet<Class<?>>();
classes.add(MyFeature.class);
// Register other providers or resources.
return classes;
}
}
register MyResolverBinder or Feature in the ResourceConfig
new ResourceConfig()
// Register either MyFeature
.register(MyFeature.class)
// or MyResolverBinder
.register(new MyResolverBinder())
// Register other providers or resources
.packages("my.package");
Providing an implementation of InjectionResolver only helps with injection, not when resolving values for the parameters of a resource method.
At least with Jersey 2.11, you need to define a ValueFactoryProvider annotated with #Provider.
#Provider
public class MyValueFactoryProvider implements ValueFactoryProvider {
#Inject
private MyFactory factory;
#Override
public Factory<?> getValueFactory(Parameter parameter) {
if (parameter.getAnnotation(MyAnnotationParam.class) != null) {
return factory;
}
return null;
}
#Override
public PriorityType getPriority() {
return Priority.NORMAL;
}
}
If you also want to get the value injected in, e.g., members and constructor parameters, then InjectionResolver works well.
I have MethodInterceptor with dependencies. How could I inject them?
Here, in 2007, Bob Lee said that this possibility should be included in next release, but I can't find API for this.
bindInterceptor method requires instances instead of classes.
From the Guice FAQ:
In order to inject dependencies in an AOP MethodInterceptor, use requestInjection() alongside the standard bindInterceptor() call.
public class NotOnWeekendsModule extends AbstractModule {
protected void configure() {
MethodInterceptor interceptor = new WeekendBlocker();
requestInjection(interceptor);
bindInterceptor(any(), annotatedWith(NotOnWeekends.class), interceptor);
}
}
Another option is to use Binder.getProvider and pass the dependency in the constructor of the interceptor.
public class NotOnWeekendsModule extends AbstractModule {
protected void configure() {
bindInterceptor(any(),
annotatedWith(NotOnWeekends.class),
new WeekendBlocker(getProvider(Calendar.class)));
}
}