GWT and Spring: EditActivity trying to invoke persist method on a request - spring

I am making some tries with GWT and Spring Roo with a simple project. The code generation seems to work fine, except for the *EditActivity classes; in fact, in such classes I get some code invoking the persist method, i.e. something like:
#Override
protected RequestContext createSaveRequest(MyEntityProxy proxy) {
request.persist().using(proxy);
return request;
}
However, that request (of type MyEntityRequest) doesn't seem to have any persist method. It extends MyEntityRequest_Roo_Gwt, which extends extends RequestContext.
#RooGwtRequest("mybasepackage.shared.domain.MyEntity")
#ServiceName(value = "mybasepackage.service.MyEntityService", locator = "mybasepackage.server.locator.GwtServiceLocator")
public interface MyEntityRequest_Roo_Gwt extends RequestContext
Where should I look for the problem? How can I fix it?

Making the "push in" to remove the aspects resolved the issue.

Related

Injection of bean inside ClientHeadersFactory doesn't work

I'm building a Quarkus app which handles http requests with resteasy and calls another api with restclient and I need to propagate a header and add another one on the fly so I added a class that implements ClientHeadersFactory.
Here's the code:
#ApplicationScoped
public abstract class MicroServicesHeaderHandler implements ClientHeadersFactory {
#Inject
MicroServicesConfig config;
#Override
public MultivaluedMap<String, String> update(MultivaluedMap<String, String> incomingHeaders,
MultivaluedMap<String, String> clientOutgoingHeaders) {
// Will be merged with outgoing headers
return new MultivaluedHashMap<>() {{
put("Authorization", Collections.singletonList("Bearer " + config.getServices().get(getServiceName()).getAccessToken()));
put("passport", Collections.singletonList(incomingHeaders.getFirst("passport")));
}};
}
protected abstract String getServiceName();
My issue is that the injection of the config doesn't work. I tried both with #Inject and #Context, as mentioned in the javadoc of ClientHeadersFactory. I also tried to make the class non abstract but it doesn't change anything.
MicroServicesConfig is a #Startup bean because it needs to be initialized before Quarkus.run() is called, otherwise the hot reload doesn't work anymore, since it's required to handle requests.
Here's the code FYI:
#Getter
#Startup
#ApplicationScoped
public final class MicroServicesConfig {
private final Map<String, MicroService> services;
MicroServicesConfig(AKV akv, ABS abs) {
// some code to retrieve an encrypted file from a secure storage, decrypt it and initialize the map out of it
}
It appears to be an issue with ClientHeadersFactory because if I inject my bean in my main class (#QuarkusMain), it works. I'm then able to assign the map to a public static map that I can then access from my HeaderHandler with Application.myPublicStaticMap but that's ugly so I would really prefer to avoid that.
I've searched online and saw several people having the same issue but according to this blogpost, or this one, it should work as of Quarkus 1.3 and MicroProfile 3.3 (RestClient 1.4) and I'm using Quarkus 1.5.2.
Even the example in the second link doesn't work for me with the injection of UriInfo so the issue doesn't come from the bean I'm trying to inject.
I've been struggling with this for weeks and I'd really like to get rid of my workaround now.
I'm probably just missing something but it's driving me crazy.
Thanks in advance for your help.
This issue has finally been solved in Quarkus 1.8.

Configuring Spring MockMvc to use custom argument resolver before built-in ones

I have a straightforward test case. I have a controller which has a parameter of a type Spring doesn't support by default, so I wrote a custom resolver.
I create the mock mvc instance I'm using like so:
mvc = MockMvcBuilders.standaloneSetup(controller).setCustomArgumentResolvers(new GoogleOAuthUserResolver()).build();
However, Spring is also registering almost 30 other argument resolvers, one of which is general enough that it is getting used to resolve the argument before mine. How can I set or sort the resolvers so that mine is invoked first?
This worked for me without reflection:
#RequiredArgsConstructor
#Configuration
public class CustomerNumberArgumentResolverRegistration {
private final RequestMappingHandlerAdapter requestMappingHandlerAdapter;
#PostConstruct
public void prioritizeCustomArgumentResolver () {
final List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>(Objects.requireNonNull(requestMappingHandlerAdapter.getArgumentResolvers()));
argumentResolvers.add(0, new CustomerNumberArgumentResolver());
requestMappingHandlerAdapter.setArgumentResolvers(argumentResolvers);
}
}
The issue was that the People class the Google OAuth library I am using extends Map and the mock servlet API provides no way to manipulate the order in which the handlers are registered.
I ended up using reflection to reach into the mocks guts and remove the offending handler.

spring boot error page with resource handlers

tl;dr: how to enable spring's ResourceUrlEncodingFilter for spring boot Error pages?
(Question written while using spring boot 1.3.7.RELEASE and Spring Framework/MVC 4.2.4.RELEASE)
Some background: We have a fairly standard spring boot/spring webmvc project using Thymeleaf as the view layer. We have the out-of-the-box spring boot Resource Chain enabled to serve static assets.
Our thymeleaf views have standard url-encoding syntax in them such as <script th:src="#{/js/some-page.js}"></script>. This relies on Spring's org.springframework.web.servlet.resource.ResourceUrlEncodingFilter to transform the url into an appropriately-versioned url such as /v1.6/js/some-page.js.
Our error handling is done by:
setting server.error.whitelabel.enabled=false
subclassing spring boot's default BasicErrorController to override public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response)
relying on our already-configured thymeleaf view resolvers to render our custom error page
The problem is: the ResourceUrlEncodingFilter isn't applying on our error pages. I assume it's a lack of the filter being registered for ERROR dispatched requests, but it's not obvious to me: a) how to customize this in spring boot; and b) why this wasn't done by default.
Update 1:
The issue seems to be with a combination of OncePerRequestFilter and the ERROR dispatcher. Namely:
ResouceUrlEncodingFilter does not bind to the ERROR dispatcher by default. While overriding this is messy it's not impossible, but doesn't help due to:
OncePerRequestFilter (parent of ResourceUrlEncodingFilter) sets an attribute on the Request indicating it's been applied so as to not re-apply. It then wraps the response object. However, when an ERROR is dispatched, the wrapped response is not used and the filter does not re-wrap due to the request attribute still being present.
Worse still, the logic for customizing boolean hasAlreadyFilteredAttribute is not overridable by request. OncePerRequestFilter's doFilter() method is final, and getAlreadyFilteredAttributeName() (the extension point) does not have access to the current request object to get the dispatcher.
I feel like I must be missing something; it seems impossible to use versioned resources on a 404 page in spring boot.
Update 2: A working but messy solution
This is the best I've been able to come up with, which still seems awfully messy:
public abstract class OncePerErrorRequestFilter extends OncePerRequestFilter {
#Override
protected String getAlreadyFilteredAttributeName() {
return super.getAlreadyFilteredAttributeName() + ".ERROR";
}
#Override
protected boolean shouldNotFilterErrorDispatch() {
return false;
}
}
public class ErrorPageCapableResourceUrlEncodingFilter extends OncePerErrorRequestFilter {
// everything in here is a perfect copy-paste of ResourceUrlEncodingFilter since the internal ResourceUrlEncodingResponseWrapper is private
}
// register the error-supporting version if the whitelabel error page has been disabled ... could/should use a dedicated property for this
#Configuration
#AutoConfigureAfter(WebMvcAutoConfiguration.class)
#ConditionalOnClass(OncePerErrorRequestFilter.class)
#ConditionalOnWebApplication
#ConditionalOnEnabledResourceChain
#ConditionalOnProperty(prefix = "server.error.whitelabel", name = "enabled", havingValue="false", matchIfMissing = false)
public static class ThymeleafResourceUrlEncodingFilterErrorConfiguration {
#Bean
public FilterRegistrationBean errorPageResourceUrlEncodingFilterRegistration() {
FilterRegistrationBean reg = new FilterRegistrationBean();
reg.setFilter(new ErrorPageCapableResourceUrlEncodingFilter());
reg.setDispatcherTypes(DispatcherType.ERROR);
return reg;
}
}
Better solutions?
This has been reported in spring-projects/spring-boot#7348 and a fix is on its way.
It seems you've made an extensive analysis of the issue; too bad you didn't report this issue earlier. Next time, please consider raising those on the Spring Boot tracker.
Thanks!

Using Aspect to annotate methods with #InsightOperation for Spring Insight

I wanted to instrument a large number of classes to use with Spring Insight and instead of adding the #InsightOperation manually to the methods, I wrote an aspect to annotate the methods using point cuts.
However, this is not working. While the manual annotation affects the Spring Insight trace logging, the AspectJ method does not work.
Is there anything I am doing wrong here? (I decompiled the classes after aspectizing and do find the annotation in the class methods)
This is the aspect code snippet:
declare #method :public * com.example.IExample.execute(..) : #InsightOperation;
Spring documentation says this:
Use of the #Insight* annotations are
optional. They make it easy for end
users to define custom operation
frames and end points without needing
to create a plug-in. Because end user
code modification is required to use
the annotations, they are an option
for users who cannot or do not wish to
write aspects.
http://static.springsource.com/projects/tc-server/2.5/devedition/htmlsingle/devedition.html
So looks like the only way is to write a custom plugin
http://static.springsource.com/projects/tc-server/2.5/devedition/htmlsingle/devedition.html#tutorial-plugin
It is possible that the Insight LTW does not pick up your introduced annotations. I'll have to dig deeper on that.
In the meantime, you can try a more low-level annotation:
com.springsource.insight.collection.method.MethodOperationsCollected
If you look at the spring-core plugin, you will see that it does something similar:
public aspect RepositoryMethodOperationCollectionAspect {
declare #type: #Repository * : #MethodOperationsCollected;
}
An easy work around is to call another method from within your aspect method to continue executing the join point. I only tried calling a static method in a static class. See below my code for adding the #InsightOperation to all my JSON serialization.
My aspect:
#Aspect
public class JSONSerializerAspect {
#Around("call(* *.JSONSerializer.serialize(..)) && args(target)")
public Object serialize(ProceedingJoinPoint joinPoint, Object target) throws Throwable {
return JSONSerializationWrapper.serialize(joinPoint, target);
}
}
The static class it is calling:
public class JSONSerializationWrapper {
#InsightOperation(label = "JSON_SERIALIZATION")
public static Object serialize(ProceedingJoinPoint joinPoint, Object target) throws Throwable {
return joinPoint.proceed(new Object[]{target});
}
}
I'm using this myself and tested that it works.

Spring AnnotationMethodHandlerAdapter and annotation-reading interceptors

I have a basic Spring MVC controller that looks like this:
#Controller
public void MyController {
#RequestMapping("/secret")
public String show() {
return "secret.jsp";
}
}
I am going to have several similar URLs that can only be reached by signed-in users. Since this is a cross-cutting concern, I'd like to use AOP, and I'd like to make this work via annotations. In other words, I'd like to throw a #RequiresLogin annotation on every controller method that needs to be secret.
AnnotationMethodHandlerAdapter supports the concept of interceptors, which seems on the surface like the right way to go for this. However, I want to know which method is going to be invoked so that I can check it for my #RequiresLogin annotation. I see that there's an "Object handler" parameter that's passed in, but I'm not sure how to turn that into a Class and Method that will be invoked.
Ideas?
There are no good ways to get a method signature in the interceptor.
Try to apply a regular AOP advise to your controller, Spring MVC plays well with it as long as target class proxying is used.
As axtavt writes correctly, Spring-AOP works well with controllers if using proxy-target-class. But there is also the possibility of using JDK proxies if you follow some (tedious) conventions:
Working with interface-based #Controller classes
A common pitfall when working with
annotated controller classes happens
when applying functionality that
requires creating a proxy proxy for
the controller object (e.g.
#Transactional methods). Usually you
will introduce an interface for the
controller in order to use JDK dynamic
proxies. To make this work you must
move the #RequestMapping annotations
to the interface as the mapping
mechanism can only "see" the interface
exposed by the proxy. As an
alternative, you may choose to
activate proxy-target-class="true" in
the configuration for the
functionality applied to the
controller (in our transaction
scenario in <tx:annotation-driven />).
Doing so indicates that CGLIB-based
subclass proxies should be used
instead of interface-based JDK
proxies. For more information on
various proxying mechanisms see
Section 7.6, “Proxying mechanisms”.
Source: 15.3.2 Mapping requests with #RequestMapping
While using spring security would be the optimal approach here, you can implement similar functionality using Spring Aspects. Here is an example of using an Aspect to check for a method containing a particular Annotation.
#Aspect
public class MyAspect {
#Around("execution(* com.test.controllers..*.**(..)) && " +
"within(#org.springframework.sterotype.Controller *)")
public Object execute(ProceedingJoinPoint joinPoint) {
Object target = joinPoint.getTarget();
if (target != null) {
Signature tSig = joinPoint.getSignature();
if (tSig instanceof MethodSignature) {
MethodSignature mSig = (MethodSignature) tSig;
Method method = mSig.getMethod();
if (method != null && method.isAnnotationPresent(MyAnnotation.class)) {
// do something
// parameters are available from joinPoint.getArgs();
}
}
}
}
// allow method invocation to continue
return joinPoint.proceed();
}
The format of the #Around advice will be specific to your application. In this example, it checks for any class annotated with Controller in the package com.test.controllers and all subpackages. See http://static.springsource.org/spring/docs/3.0.x/reference/aop.html for additional options.
Good luck!
How about ResolveHandlerMethodInterceptor using reflection.
Below code is experimental and version-dependent(spring 3.0.2).
import java.lang.reflect.Method;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.FrameworkServlet;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
public class ResolveHandlerMethodInterceptor implements HandlerInterceptor {
public final static String HANDLER_METHOD = "handlerMethod";
// Here is your servlet name
public final static String SERVLET_NAME = "XXXXX";
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView modelAndView)
throws Exception {
Method handlerMethod = (Method) request.getAttribute(HANDLER_METHOD);
System.out.println("postHandle>>>" + handlerMethod);
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception exception)
throws Exception {
Method handlerMethod = (Method) request.getAttribute(HANDLER_METHOD);
System.out.println("afterCompletion>>>" + handlerMethod);
}
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
ServletContext servletContext = request.getSession().getServletContext();
String attrName = FrameworkServlet.SERVLET_CONTEXT_PREFIX + SERVLET_NAME;
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext, attrName);
AnnotationMethodHandlerAdapter adapter = context.getBean(AnnotationMethodHandlerAdapter.class);
Method getMethodResolverMethod = adapter.getClass().getDeclaredMethod("getMethodResolver", Object.class);
getMethodResolverMethod.setAccessible(true);
Object servletHandlerMethodResolver = getMethodResolverMethod.invoke(adapter, object);
Method resolveHandlerMethod = servletHandlerMethodResolver.getClass().getMethod("resolveHandlerMethod", HttpServletRequest.class);
resolveHandlerMethod.setAccessible(true);
Method handlerMethod = (Method) resolveHandlerMethod.invoke(servletHandlerMethodResolver, request);
request.setAttribute(HANDLER_METHOD, handlerMethod);
System.out.println("preHandle>>>" + handlerMethod);
return true;
}
}
==reference==
http://toby.epril.com/?p=934
http://www.jarvana.com/jarvana/view/org/springframework/spring-webmvc/3.0.2.RELEASE/spring-webmvc-3.0.2.RELEASE-sources.jar!/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java?format=ok
So, these approaches listed are good, but they all have limitations. The AOP stuff is a good idea, but its limitation is that I need a way to get ahold of the request and response objects if I want to redirect or modify the response. The controller methods don't necessarily need the requests and responses, and requiring that they appear seems inelegant. I could use spring magic to get the request object from the Aspect, but I couldn't find a way to get the response.
Eventually, I came up with a middle way. I used a filter bean to get the request and the response objects and store them in a ThreadLocal. Then I created an aspect that has a reference to that filter, so that it could easily see the request and response objects.
Then I made the aspect wrap around methods based on the annotation, so I didn't even need to check on whether the annotation was present using code.
This combination approach appears to be working perfectly!
The only downside is that I can't figure out a good way to write an integration test that verifies that the aspect is invoked when there's an incoming request to that URL. It's a little scary that removing a single annotation leaves all my tests passing but allows unauthorized users through.
Thanks everybody for the great suggestions!

Resources