After upgrading from Spring Boot 1.3.8 to Spring Boot 1.4.4 I get a NullPointerException in AbstractRememberMeServices because the logger isn't instantiated successfully.
A NullPointerException is thrown on this Line.
I write a custom RememberMeService which extends AbstractRememberMeServices. This service is registered as a bean as you can see in the following code snipped:
#Bean
RememberMeServices rememberMeServices(UserDetailsService userDetailsService, UserRepository userRepository, RememberMeTokenRepository rememberMeTokenRepository, RandomService randomService) {
String key = env.getProperty("security.rememberme.key");
RememberMeService rememberMeService = new RememberMeService(key, userDetailsService, userRepository, rememberMeTokenRepository, randomService);
rememberMeService.setAlwaysRemember(true);
return rememberMeService;
}
This error seems related to this SO question. Additionally JHipster has a similar issue.
Does anyone know why the logger isn't instantiated successfully?
I know this is an old question but I just encountered the same thing in a library's custom RememberMeServices impl. You may find an indication of the problem mentioned in the Spring startup logs. For instance:
2018-04-11 07:32:07.311 INFO 1 --- [ost-startStop-1] o.s.a.f.CglibAopProxy : Final method [public final org.springframework.security.core.Authentication org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices.autoLogin(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)] cannot get proxied via CGLIB: Calls to this method will NOT be routed to the target instance and might lead to NPEs against uninitialized fields in the proxy instance.
In this case, the subclass must have some feature that requires proxying by CGLIB, such as #Transactional on a method. If no such features were present, CGLIB wouldn't be necessary and the subclass would behave as expected.
Also got this error. When I debug, I find out the properties of AbstractRememberMeServices almost all null. Then I think, maybe the inject of spring not work. So I changed my code to this:
.rememberMe()
.rememberMeServices(new MyRememberMeServices(env, userDetailsService, userRepo, tokenRepo))
.and();
It works. But I don't understand why...
Related
This question already has an answer here:
Bean 'x' of type [TYPE] is not eligible for getting processed by all BeanPostProcessors
(1 answer)
Closed 2 years ago.
upon configuring actuator to start up on a distinct port, the app fails with the following stacktrace:
java.lang.NullPointerException: null
at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:241) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:270) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:106) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4528) [tomcat-embed-core-9.0.37.jar:9.0.37]
aop issues the following info warning:
2020-08-16 10:01:11.240 INFO 83848 --- [ main] o.s.aop.framework.CglibAopProxy : Unable to proxy interface-implementing method [public final void org.springframework.web.filter.GenericFilterBean.init(javax.servlet.FilterConfig) throws javax.servlet.ServletException] because it is marked as final: Consider using interface-based JDK proxies instead!
here are my gradle dependencies:
plugins {
id 'org.springframework.boot' version '2.3.3.RELEASE'
...
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.1.5.RELEASE'
implementation 'org.springframework.security:spring-security-jwt:1.0.10.RELEASE'
we do have one #Aspect annotated class:
...
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.security.web.firewall.RequestRejectedException;
import org.springframework.stereotype.Component;
...
#Aspect
#Component
#Slf4j
public class MyFilter {
#Around("execution(public void org.springframework.security.web.FilterChainProxy.doFilter(..))")
public void handleRequestRejectedException (ProceedingJoinPoint pjp) throws Throwable {
try {
pjp.proceed();
} catch (RequestRejectedException exception) {
...
}
}
}
i have found a few issues discussing this problem, having something to do with aop, but i have as of yet failed to find a solution.
any/all help appreciated.
james
After the OP has updated the question with some sample code, I see that the problem is not a pointcut which is too generic, capturing too many classes like in the other question I linked to in my comment but something else:
James, you are targeting method FilterChainProxy.doFilter(..), i.e. directly a Spring framework class. The problem is, as you can also see in the error message you get in your log:
o.s.aop.framework.CglibAopProxy:
Unable to proxy interface-implementing method [
public final void org.springframework.web.filter.GenericFilterBean.init(javax.servlet.FilterConfig)
throws javax.servlet.ServletException
]
because it is marked as final:
Consider using interface-based JDK proxies instead!
The problem is that the target class is derived from GenericFilterBean where the init(..) method is marked as final. CGLIB works via subclassing and overriding non-private methods, but a final method cannot be overridden. Thus, Spring AOP complains.
The error message also hints you towards a solution for the problem: Instead of using a CGLIB proxy for the target, you could use a JDK proxy which works by implementing interfaces. Luckily, doFilter is an interface method, more precisely an implementation of JavaEE method Filter.doFilter(..).
Now the next problem is that you are not using plain vanilla Spring but Spring Boot, which is known for having a combination of presets which seem to make it impossible to switch to JDK proxies, even though in plain Spring that is even the default. But Boot wants to be too user-friendly and smart, leaving you in this trap. I do not remember the Spring Boot ticket dealing with this problem, but last time I checked it was unresolved.
One way to avoid the whole situation is to use full AspectJ instead of just Spring AOP for your aspect, thus freeing you of the proxy-based "AOP lite" approach and enabling you to directly modify the target class or to alternatively weave your aspect not into the target class but into all calling classes instead via call() pointcut (not supported by Spring AOP).
Another solution would be to hook into another, less problematic target class/method with your aspect, not directly into a Spring framework class with final methods.
P.S.: I am not a Spring user, I just happen to know a few details from answering AOP-related questions here. Actually, I am surprised that CGLIB proxying as implemented by Spring is not more lenient with regard to final methods, just ignoring them and logging a warning instead of trying to override them and producing an error. Maybe there is some configuration option for that, but I leave it up to the Spring folks to answer that question, I have no clue here.
I cannot answer more precisely because I would need to see a full MCVE, ideally a Maven or Gradle project on GitHub, in order to further analyse your situation. I just wanted to explain some basics here.
I am trying to build a token based authentication and authorization system using Apache CXF and Spring. I am completely following this fantastic post for doing this.
But I am stuck in a problem with my AuthorizationFilter at the very beginnig. I have seen many posts, apache JIRA, github comments about it, but could not yet found the workaround about this seemingly CXF issue.
#PreMatching
#Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter {
private ResourceInfo resourceInfo;
#Context
public void setResourceInfo(ResourceInfo resourceInfo) {
this.resourceInfo = resourceInfo;
}
#Override
public void filter(final ContainerRequestContext requestContext) throws IOException {
Method method = resourceInfo.getResourceMethod();
In the above code, the injected resourceInfo is a proxy object, and it has none of the associated properties present. So, anything from that resourceInfo object is returning null, more specifically resourceInfo.getResourceMethod() is null, leading to NPE.
This is the JIRA post pertaining to this very issue, saying that:
In some circumstances (like using #ApplicationScoped annotation for example) the CDI runtime will create a proxy class for a particular bean. As the result, the CXF side is going to bind the particular provider metadata to this proxy instance. It looks logical and unambiguous.
However, the interesting things are happening when CXF will try to inject contextual proxies (#Context annotations) into the provider instance. The injections are successful but the target object for them will be the proxy instance (not the real instance behind it). Consequently, at runtime, when the proxy delegates the call to a backing instance, all contextual proxies are null in there (simply put, not set).
Referring to the recent discussions with Sergey Beryozkin, the best solution would be to delegate the #Context annotation to CDI framework (as such, relieving the CXF from doing the injection work). This proposal may need a support from the JAX-RS specification side.
Simpler (interim?) possible solution would be to complement the CDI injection with #Context injection (delegating this work to the CXF as it works right now for non-proxy beans and non-CDI deployments). This could be done by observing ProcessInjectionTarget events and supplying our own InjectionTarget (have working PoC for this approach).
Regarding constructor injection, it seems like CXF does not support passing the arguments to provider constructor (in case of CDI, w/o #Context annotation) so I it would be another (separate) issue to look at.
Can someone help me point out what is this simpler approach is all about:
Simpler (interim?) possible solution would be to complement the CDI injection with #Context injection (delegating this work to the CXF as it works right now for non-proxy beans and non-CDI deployments). This could be done by observing ProcessInjectionTarget events and supplying our own InjectionTarget (have working PoC for this approach)
Or is there any other way, where Spring Framework can inject the ResourceInfo object in a correct way?
I have registered the filters like this in my applicationContext.xml :
<jaxrs:server id="endpoints">
<jaxrs:providers>
<ref bean="authenticationFilter" />
<ref bean="authorizationFilter" />
</jaxrs:providers>
</jaxrs:server>
The problem is the #PreMatching annotation.
Global binding annotation that can be applied to a container request filter to indicate that such filter should be applied globally on all resources in the application before the actual resource matching occurs.
The key is highlighted part "before the actual resource matching occurs". So even before the resource is matched to the request, the filter is called. And if there is no resource matched yet, then it is impossible to get any information from the ResourceInfo. If you just remove the #PreMatching annotation, then the filter will be called after a matching resource is found, and you will be able to access all the info from the ResourceInfo.
I'm trying to hide a REST endpoint based on runtime configuration in Spring and Jersey. The most straightforward way is to throw the NotFoundException from the controller itself but maybe there's more kosher. The controller is registered in the constructor of the config class which extends org.glassfish.jersey.server.ResourceConfig.
I thought of using the #Profile annotation on the controller but I can still access the endpoint. When I hit that endpoint, I get the following error:
o.g.j.s.s.SpringComponentProvider - None or multiple beans found in Spring context
but then Jersey manages to access that controller, which I confirmed by attaching a debugger to the Spring process. So Jersey does not honor the #Profile setting.
On a separate note, I also have Swagger plugged into Jersey and when accessing the definition endpoint (.../swagger.json) I can see the endpoint provided by the #Profile-disabled controller.
Is there anything better I can do here is is throwing the NotFoundException the best option?
Note: Sorry, I thought I saw that you were using Spring Boot. The following answer is only relevant for Spring Boot.
#Profile is only good for Spring bean registration, but you are still registering the service with Jersey as a resource. What you can do is use a ResourceConfigCustomizer and add the #Profile to the customizer. This way it will only register the resource with Jersey ResourceConfig if the correct profile is active.
#Component
#Profile("..")
public class MyResourceConfigCustomizer implements ResourceConfigCustomizer {
#Override
public void customize(ResourceConfig config) {
config.register(MyResource.class);
}
}
My test class looks like this
#SpringBootTest(webEnvironment=WebEnvironment.MOCK)
public class sampleClassTest{
#Autowired
private WebApplicationContext wac;
}
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
In the setup method, wac is always null. From spring boot documentation, #SpringBootTest(webEnvironment=WebEnvironment.MOCK) always created a mock WebapplicaitonContext.
So I would expect it get autowired in the code above which doesn't happen.
Can someone tell me how to go about creating a webapplicationContext in this case so that it's not null like in my case ?
UPDATE
I am running spring boot tests invoking them from a class with springboot annotation.
Both test (springboottest) and calling class (springboot) application are in the same spring boot project under src/main/java.
I have nothing under src/main/test. I have done in this way because if classes from src/main/java want to call a test class then, it isn't really a test class.
Now, the problem is that I can't use runWith(SpringRunner.class) in springbootTest class. If I did that to get a mock webApplicationContext then, it gives me this error:
javax.management.InstanceAlreadyExistsException: org.springframework.boot:type=Admin,name=SpringApplication
I am not sure how to do about this.
To use #SpringBootTest you need to use Spring Framework's test runner. Annotate your test class with #RunWith(SpringRunner.class).
If someone is struggling with this issue in 2022 - please keep my defined precondions in mind. If you are using #SpringBootTest with defined port and constructor auto-wiring of the test class, the application context might be null.
It seems that the constructor dependency injection is eager and the cache aware context delegate of Spring is searching for a web application context which is no available yet. If you use field auto-wiring your test might run in a deterministic manner.
Whoever is facing this issue, make sure your spring boot starter parent version is compatible with spring cloud version in pom.xml
I was facing same issue, i resolved it by doing same.
Does anyone know why when I try to create an advice around the "doAuthentication" method of the Spring Security (v3.0) ProviderManager my application throws an exception on startup?
I am autowiring an instance of my spring authentication-manager bean into a controller and when the autowire is attempted my app fails to deploy.
Here is what my security context xml looks like...
...<authentication-manager alias="authenticationManager"> ...
Here is the pertinent part of my controller...
#Autowired
private ProviderManager authenticationManager;
and here is my advice declaration:
#After("execution(* org.springframework.security.authentication.ProviderManager.doAuthentication(..)) && args(authentication)")
Any help will be greatly appreciated!
I'm not sure from the available information, but I'm guessing that you're using Spring AOP, which uses JDK dynamic proxies by default, so you are coming across the usual problem that the proxy does not retain the type of the original class (ProviderManager). The proxy will implement the interface AuthenticationManager, however. Try autowiring using this type and see if it works. Either that or you can enable class proxying which uses cglib instead of dynamic proxies. If you're using the Spring AOP namespace, you can set the proxy-target-class attribute to true.