I am trying to add some metric gathering to a Spring MVC app. Lets say I have a controller whose mapping is:
/User/{username}/Foobar
I want to gather metrics on all controller mapping invocations with the path. Right now I can create a handler/interceptor and look at the requests but that will give me:
/User/Charlie/Foobar
Which is not what I want. I want the controller mapping itself to log. and I don't want to have to add something to every controller. I'd also rather not use AOP if I can help it.
It turns out that Spring hangs the best matching controller pattern on the request itself. You can get this from within a handlerinterceptor like this:
(String)request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE)
I can think of two choices:
It seems to me the results of the matching are obtained in the class org.springframework.web.servlet.handler.AbstractUrlHandlerMapping, which logs the patterns obtained (see line 266). I'd try enabling logging for that class and see if the output is helpful for your purposes.
(Complicated)
Extending org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping to override the lookupHandler method inherited from AbstractUrlHandlerMapping and logging/registering what you need. Accoding to this class documentation, you can register a different one so that the DispatcherServlet uses your version.
In Spring 3.2.x DefaultAnnotationHandlerMapping is deprecated so, a different class would have to be used.
Related
I'm using Spring Boot with micrometer-registry-prometheus, trying to store custom tags from http headers, security context, etc.
So I found MeterFilter iterface and tried to use it to store the data I need.
But MeterFilter method works after request is completed, so at that point I don't have any information about request.
Seems like the case is pretty common, is there any possibility to achieve it?
If you're using Spring MVC you can define a bean that implements WebMvcTagsProvider to take complete control over the tags that are added to metrics for request-response exchanges. Alternatively, you can define a bean that implements WebMvcTagsContributor to add to the default tags. Similarly, if you're using Spring WebFlux you can define beans that implements WebFluxTagsProvider and WebFluxTagsContributor to take complete control over the tags and contribute additional tags respectively.
Here a solution is described to handle redirects to a custom URL based on a condition via use of AccessStrategy.
This however is part of the unauthorized login logical flow therefore results into a still not-logged in user arriving at the end url we redirect to. (via getUnauthorizedUrl)
If we want to redirect the user based on a condition, say via injecting an action to the webflow, how can we manipulate the return URL to be changed into a custom one?
WebUtils.getService(requestContext) include getters of the source/originalUrl but no obvious way to set/manipulate said value through an action bean.
p.s. Currently using CAS version 5.3.x
Responses for normal web applications from CAS are built using WebApplicationServiceResponseBuilder.
If you examine this block you will find that the final response is built using WebApplicationServiceResponseBuilder bean. It is only created conditionally, if an existing bean is not already found in the context by the same name. So to provide your own, you just need to register a bean with the same name using your own #Configuration class.
#Bean
public ResponseBuilder<WebApplicationService> webApplicationServiceResponseBuilder() {
return new MyOwnWebApplicationServiceResponseBuilder(...);
}
...and then proceed to design your own MyOwnWebApplicationServiceResponseBuilder, perhaps even by extending WebApplicationServiceResponseBuilder and overriding what you need where necessary to build the final redirect logic conditionally.
To learn about how #Configuration classes work in general, you can:
Review this post
or this post
or consult the documentation for Spring and/or Spring Boot.
I'm working on securing a REST Service endpoints with Spring Security. I basically need to check if user has given Authority, if the user can invoke the function with the given parameters, and lastly, I filter the output, so that the user cannot see things that it shouldn't.
For this, I have this set of annotations:
#PostFilter("#canViewOwnAssignment.canView(filterObject) or #canViewAllAssignments.canView(filterObject)")
#PreAuthorize("hasAnyAuthority('canViewOwnAssignment', 'canViewAllAssignments') and (#canViewOwnAssignment.canEnter(userId) or #canViewAllAssignments.canEnter(userId))")
...for all the methods. The only thing changing from the above snippet is canViewOwnAssignment and the parameter(s) of .canEnter().
I'd like to simplify this, so that I can have an annotation looking sg like this:#MyAnnotation(bean = CanViewAssignment.class, args = {"userId"})
How could I make this happen?
I tried extending PrePostAnnotationSecurityMetadataSource.class, since that's the one parsing the annotations, however I can't just use #Primary to override it, since the bean instantiation is baked into the GlobalMethodSecurityDefinitionParser.class
If I don't need to, I'd rather not start rewriting half of the Spring Security, only to have one overriden method.
I'm just new into Spring Framework tech and I'm making a website with few WebServices(Webstore, social media site etc.) included. What I want for it, is that every webservice would have it owns DispatcherServlet with own ViewResolver. So the structure of my projects looks like:
The Main site - DispatcherServlet #1 mapping only to http://example.com (yeah, i know i could just use static html site but it's for learning purposes.
Webservice no.1 e.g Webstore - DispatcherServlet #2 mapping only to
/webstore/*
Webservice no.2 e.g Social media site - DispatcherServlet #3 mapping only to /social/*
In configuration I'm using Java Classes, so what I did was:
Firstly I've Created AppConfig class that extends WebMvcConfigureAdapter and
implements ViewResolver for main site views. Next I've created An AppInitializer class which extends AbstractAnnotationConfigDispatcherServletInitializer class and inside of it I've configured RootConfigClass and servlet mapping
Secondly I've had problem - namely I couldn't create another class for Dispatcher Servlet #2 (couldn't have two classes which extended AbstractAnnotationConfigDispatcherServletInitializer ), what I've found was creating class which would implement an interface WebApplicationInitializer. Which I did and finally had working Second DispatcherServlet
Thirdly I've reapeted steps from second point and had Three working Dispatcher Servlets(in theory...).
I could access my main site via DispatcherServlet #1
(http://example.com)
I could access my webstore main site via DispatcherServlet #2 (http://example.com/webstore)
and I could access my webservice via DispatcherServlet #3(http://example.com/social)
but after all, when I've created another view pointing e.g. to login section (http://example.com/webstore/login) It didn't work at all. The errors said that Dispatcher Servlet #1 couldn't handle mapping request, where the address should be tied with Dispatcher Servlet #2. What I did to resolve this problem was changing The Dispatcher Servlet #2 configuration class part of servlet mapping from servlet.addMapping("/webstore/"); to servlet.addMapping("/webstore/*"); which I've read is not the best idea but It worked.
The problem appears when I would type address that Controller doesn't handle(doesn't exists) like (http://example.com/webstore/thisaddressdoesntexists), the view controller gives me back main default view from http://example.com/webstore, instead of 404 not found page. This is not the behavior I've intented to implement. Besides that little 'feature', everything works fine. All specyfic request are served with their specyfic DispatcherServlet. Finnal questions are:
How to prevent from loading default view, in this case scenario, when I'm pointing to non-existing url and load error code sites?
Is my concept even good at all? I mean using classes which implements WebApplicationInitializer for using more DispatcherServlets or there is another way? I'm only talking about Java-Based Config Classes, no xmls.
Is my concept even good at all? I mean using classes which implements
WebApplicationInitializer for using more DispatcherServlets or there
is another way? I'm only talking about Java-Based Config Classes, no
xmls.
For multiple servlets you need to have a single class which implements WebApplicationInitializer and there provide contextLoader class with all beans for the root context and define a separate class with all the beans for each servlet (usualliy the class which extends WebAppConfigurer). You also need to provide a mapping for each individual servlet. Have a look here how it's done as an example (the last 2 responses)
As regards to
Is my concept even good at all?
Why do you want to have three separate servlets? Are these three different apps bundled together? If that's the case I wouldn't put them in the same package but make three 3 different apps. You can also use a single Dispatchetservlet which maps to every url and have separate controllers for each component. That will reduce the complexity of the whole project. So it could be either way. Without knowing more about what you are trying to do no one can say it's right or wrong.
How to prevent from loading default view, in this case scenario, when
I'm pointing to non-existing url and load error code sites?
For error handling page have a look here. You would normally use #ResponseStatus for a specific HTTP error code or #ExceptionHandler for a general purpose error. In both cases you would need to redirect to a default error page.
I think what I need is called reverse url resolution in Django. Lets say I have an AddUserController that goes something like this:
#Controller
#RequestMapping("/create-user")
public class AddUserController{ ... }
What I want is some way to dynamically find the url to this controller or form a url with parameters to it from the view (JSP), so I don't have to hardcode urls to controllers all over the place. Is this possible in Spring MVC?
Since Spring 4 you can use MvcUriComponentsBuilder.
For the most type-safe method:
String url = fromMethodCall(on(MyController.class).action("param")).toUriString();
Note this example requires that the method returns a proxyable type - e.g. ModelAndView, not String nor void.
Since 4.2, the fromMappingName method is registered as a JSP function called mvcUrl:
Login
This method does not have the proxy restriction.
Have you considered having a bean that aggregates all of the controller URLs you need into a HashMap and then adding this controller/URL Map to any model that requires it? Each Spring controller has the ability to call an init() method, you could have each controller add it's name and URL to the controller/URL map in the init() methods so it would be ready to use when the controllers go live.
Can solve with Java Reflection API. By Creating Custom Tag library. methods looks like this
Class c = Class.forName("Your Controller");
for(Method m :c.getMethods()){
if(m.getName()=="Your Method"){
Annotation cc = m.getAnnotation(RequestMapping.class);
RequestMapping rm = (RequestMapping)cc;
for(String s:rm.value()){
System.out.println(s);
}
}
}
Possible Problem You Can Face is
1.Path Variable > Like this /pet/show/{id} so set of path name & value should be support then replace this String.replace() before return url
2.Method Overriding > only one method is no problem. if Method override Need to give support sequence of Parameter Type That you really want like Method.getParametersType()
3.Multiple Url to Single Method> like #RequestMapping(value={"/", "welcome"}). so easy rule is pick first one.
4.Ant Like Style Url > Like this *.do to solve this is use multiple url by placing ant like style in last eg. #RequestMapping(value={"/pet","/pet/*.do"})
So Possible link tag style is
<my:link controller="com.sample.web.PetController" method="show" params="java.lang.Integer">
<my:path name="id" value="1" />
</my:link>
Where parmas attribute is optional if there is no method override.
May be I left to think about some problem. :)
I would probably try to build a taglib which inspects the annotations you're using in order to find a suitable match:
<x:url controller="myController">
<x:param name="action" value="myAction"/>
</x:url>
Taglib code might be something roughly like
Ask Spring for configured beans with the #Controller annotation
Iterate in some suitable order looking for some suitable match on the controller class or bean name
If the #RequestMapping includes params, then substitute them
Return the string
That might work for your specific case (#RequestMapping style) but it'll likely get a bit hairy when you have multiple mappings. Perhaps a custom annotation would make it easier.
Edit:
AbstractUrlHandlerMapping::getHandlerMap, which is inherited by the DefaultAnnotationHandlerMapping you're most likely using, returns a Map of URL to Handler
Return the registered handlers as an
unmodifiable Map, with the registered
path as key and the handler object (or
handler bean name in case of a
lazy-init handler) as value.
So you could iterate over that looking for a suitable match, where "suitable match" is whatever you want.
You can get access to the request object in any JSP file without having to manually wire in or manage the object into the JSP. so that means you can get the url path off the request object, have a google into JSP implicit objects.
Here is a page to get you started http://www.exforsys.com/tutorials/jsp/jsp-implicit-and-session-objects.html
The problem with this is that there's no central router in SpringMVC where all routes are registered and ordered. Then reverse routing is not a static process and route resolution in the view layer can be hard to integrate.
Check out this project for a centralized router (like rails) and reverse routing in the view layer.