Get method name in Java Filter - java

Got a Java Filter which is responsible to intercept some endpoints.
In doFilter method, as follows:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
How do I get the accessed method name?
For instance:
Given 2 Servlets followed by operation name:
LifeCycle
create
delete
SearchService
findByName
findById
When LifeCycle.create operation is called by a front end perspective, the filter intercepts it, however I couldn't know if the operation called was create or delete?
Are there some way to get the "create" operation name in Java Filter?
Thanks in advance.

Filters are invoked by the web container when a request is made to the server (servlet or jsp). They are not called by Servlets or jsps.
You can see Filter's life-cycle in the image below:
For more see DOCUMENTATION
If you want to know which action is called from the front-end, then you can use a request parameter and then capture it from ServletRequest

I could get the operation name using:
((HttpServletRequest) request).getHeader("SOAPAction");

If you are searching for method names then you can try this piece of code:
StackTraceElement[] st = Thread.currentThread().getStackTrace();
String methodName = st[2].getMethodName();
You can further modify the index of st to get the chained caller methods. It is just a simple array of stack trace objects containing class and method names. Good Luck!

Related

How do i use spring mvc void controller method?

I am reading spring framework reference. When i read here. I found that spring mvc supports returning void types.And then i read some examples of using void.But these examples do not make me to understand when time to use void.Is there a better example of how to use it?
From the referenced document:
"... if the method handles the response itself (by writing the response content directly, declaring an argument of type ServletResponse / HttpServletResponse for that purpose) or if the view name is supposed to be implicitly determined through a RequestToViewNameTranslator (not declaring a response argument in the handler method signature)"
There are two conditions listed.
If the method writes to the servletResponse directly. In this case, there is nothing for spring to do; a return value of void tells spring "I got this" and it does nothing with the response.
If the view name can be determined vai a RequestToViewNameTranslator. In this situation, spring knows the view to return based on the request, so no return value is required.

How to call a Servlet/Filter before a JSP is executed in CQ5?

In a Spring MVC application we have a Controller that would execute before calling the JSP. The Controller would prefetch some values from the database and set them in the model and forward the control to JSP.
How do I implement this feature in CQ 5? I want the SlingFilter to execute before the JSP is executed. And the JSP is not a page component but a component that appears in the side kick.
Note:
I can do this by writing my own SlingSerlvet that would prefetch my required values and use the RequestDispatcher to forward to the JSP.
But by this method I would have to go through a URL like "/bin/.*". And this is again at a page level I want this kind of functionality at component level.
So to answer your specific question, if you want a filter to be executed before a component is called you would create a filter that is listening to Component level filter scope.
See
http://sling.apache.org/documentation/the-sling-engine/filters.html
You would then have your filter change the incoming request to a SlingServletRequest and determine if the target resource is the one that you are looking for.
However this filter would be executed on every single component that is being included on a page. The reverse process of this that may be useful to you is the ResourceDecorator.
http://sling.apache.org/documentation/the-sling-engine/wrap-or-decorate-resources.html
These are executed when the resource is identified, prior to the servlet and filter calls, which would allow you to verify if a resource is a type that you are interested in, and then allows you to add additional information to the resource object.However this is, once again a service that would be applied to every resource that is identified.
However, if what you are looking for is a filter that is only executed for a specific path, then no. Sling doesn't do that. You mentioned Spring MVC and Spring MVC works on a completely different concept of MVC then what Slings version of MVC does.
EDIT
So in a traditional web app, the servlet would be at a fixed position and all filters are applied prior to the call to that servlet. In Sling you are dynamically wiring servlets together to generate the resulting page. So each time that you are in a servlet and call directly or indirectly the request dispatcher, it's executing the resolution process again and applying a series of filters again before the new servlet is executed.
To prevent a high level filter that needs to applied only to the main request being applied on every single internal dispatch, they came up with the idea of contexts, or chains of filters that are applied at different times and associated with different types of includes.
Here is a basic filter that will log a message when it's called. I did this from memory so you'll need to dink with it.
#SlingFilter(scope = SlingFilterScope.COMPONENT, order = Integer.MIN_VALUE)
public class SampleFilter implements Filter {
private static final Logger LOG = LoggerFactory.getLogger(SampleFilter.class);
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
Resource res = slingRequest.getResource();
if (!(res == null || ResourceUtil.isNonExistingResource(res))) {
LOG.error("this servlet is called before resource {} at path {}", res.getName(),res.getPath());
}
chain.doFilter(request, response);
}
}
The important part of this is scope = SlingFilterScope.COMPONENT take a look at the page I had listed earlier and try out different combinations of slignfilterscope and you'll see how it's being applied at different times. scope = SlingFilterScope.REQUEST would be once at a top level on a per page basis.
JE Bailey's answer is correct as far as Filters are concerned, but I suspect your problem might be solved in a different way that better fits Sling's view of the world.
Sling promotes the use of OSGi services for business logic, and scripts should be a thin layer above that. Moving your logic to OSGi services and calling those from your scripts is the recommended way.
You might also have a look at Sling Models which can include processing steps (with #PostConstruct) before the rendering scripts kick in.
But by this method I would have to go through a URL like "/bin/.*".
You can also register a servlet against a resource type, as well as by path, e.g. (from the Sling documentation):
#SlingServlet(
resourceTypes = "sling/servlet/default",
selectors = "hello",
extensions = "html",
methods = "GET")
public class MyServlet extends SlingSafeMethodsServlet {
#Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
...
}
}
If you remove the "selectors", "extensions" and "methods" parameters on the annotation, this servlet would bind against all calls to sling/servlet/default without requiring binding against a set path.

Java Servlet and Jquery

Im currently making a Java Servlet that can respond to jquery calls and send back data for my web page to use. But this is only a response using the doGet method.
Is there a way to have multiple methods in a Servlet and call them each with JQuery?
i.e. have a method called Hello and it returns a String "Hello" and another method called Bye and it returns a String "Bye". Is there a way using Jquery or some other technology to do this kind of thing?
Im quite new to servlets so Im still not sure what they are fully capable of. So is the doGet the only method to 'get in' and I just branch responses from there?
With Servlet you can either call the service method, so may be for your scenario you could pass the parameter to decide which method to invoke from doGet()
also you could identify if request is coming from AJAX using header check
There are other technologies available which will allow you directly invoke method See JSF, DWR
See
How to invoke a method with Openfaces/JSF without rendering page?
How to call a java method from jsp by clicking a menu in html page?
Personally I use reflection in my controllers(servlets) which basically let me achieve this.
If I have a servlet called UserController
The main url to call the servlet will be /user.
Knowing this, I always pass my first parameter as ?action=add
Then in my servlet I have a method called add or actionAdd. Whichever you prefer.
Then I use the following code;
String str = String str = request.getParameter("action").toLowerCase();
Method method = getClass().getMethod(str, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this, request, response);
Explanation:
str will have the action parameters value, add in this case.
Method method will be a reference to a method with the given name(str) and its expected parameter types.
I then invoke the method, passing the context, request and response.
The add method would look something like this;
public void add(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
//do add stuff
String url = "/user/index.jsp";
RequestDispatcher dispatcher = context.getRequestDispatcher(url);
request.setAttribute("User", user);
dispatcher.forward(request, response);
}
I don't know about only passing back a string. But this should get you a basic idea.
Do note that reflection can cost you, altohugh it shouldnt really affect you much like this. And it is error prone as method names/signatures need to match perfectly.
So from jquery you would do an ajax request to the url:
localhost/projectname/user/add (if you use urlrewrite)
or
localhost/projectname/user?action=add (if you dont)
Servlet Container supports Custom Http methods since Servlet 3.0. For Ex,
public void doHello(HttpServletRequest req, HttpServletResponse res) {
//implement your custom method
}
The above method in Servlet can be invoked using hello http method.
But i am not sure if jquery has the support to invoke custom HTTP methods.
If it does not have, then the only option you have.
Invoke Servlet using GET and action parameter.
Read the action parameter and invoke the method using reflection.

servlet doGet and doPost methods [duplicate]

This question already has answers here:
doGet and doPost in Servlets
(5 answers)
Closed 6 years ago.
I want to know that in servlets why we use doGet and doPost methods together in the same program. What is the use of it??
What does the following code means?
Why to call the doGet method from doPost? I am not at all clear about this code.
public class Info extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
doGet(request, response);
}
}
Thanks
doGet() handles incoming HTTP GET requests while doPost() handles... POST requests. There are also equivalent methods to handle PUT, DELTE, etc.
If you submit your form using GET (default), the doGet() will be called. If you submit using POST, doPost() will be invoked this time. If you only implement doPost() but the form will use GET, servlet container will throw an exception.
In many programs the server doesn't care whether the request uses GET or POST, that's why one method simply delegates to another. This is actually a bad practice since these methods are inherently different, but many tutorials write it this way (for better or worse).
Simply, it is to make the servlet generalized so that even if we change the request method in future, it is not required to edit the servlet, which will reduce the efforts to modify the application in future.
This is to handle both requests type eg. GET and POST of http. depending upon app's requirement people may chose to keep request type as GET or POST so incase you are handling both of them you will get error. and in case you want to handle both of them in similar fashion then you can create another method doSomething and call it from your doGet and doPost methods for more info see this answer
Isn't it to do with a get request allows the parameters to be seen in the URL in the browser window and the post request incorporation the parameters into the structure of the request and hence hidden from view. How will your request be made from the client as a get or a post. I think it is something to do with security and avoiding sql injections, but it is not my area really. Hopefully, some expert with correct my view/comment as I need to know this myself.
As you noted here you can indeed call a third method but you also can override the service() method from the HttpServlet motherclass so that it calls alawys one unique method.

how to over ride request object in ServletRequestWrapper?

I want to over ride the default getParameter() method of ServletRequestWrapper with getParameter() method of SecurityRequestWrapper.
For example, if I am using a simple jsp form to take the name of a person,
String name = request.getParameter("firstName");
I want the above getParameter() method to be from the SecurityRequestWrapper class. I am not able to understand how the request object is over riden since the getParameter method is mostly called on it by default in any jsp form.
I understand that the SecurityRequestWrapper you're talking about already implements HttpServletRequestWrapper? If so, then just create a Filter which is mapped on an url-pattern of *.jsp (or whatever you'd like to invoke this Filter for) and does basically the following in the doFilter() method.
chain.doFilter(new SecurityRequestWrapper((HttpServletRequest) request, response));
I might be wrong, but I do not think this is possible. Because request and response objects are created by the container and passed onto the servlet's process method. The very reason these objects are created by the container, because they want to flush the output and would like to control that. I will be interested to know however if it is possible to pass our own request / response objects.

Categories

Resources