I was wondering if it is possible to call a non-life-cycle method of a servlet directly from the Browser.
For example, just as a sample code if I have something like -
public CheckServlet extends HttpServlet {
public void foo(HttpServletRequest req, HttpServletResponse res) {
// do something
}
}
web.xml -
<servlet>
<display-name>CheckServlet</display-name>
<servlet-name>CheckServlet</servlet-name>
<servlet-class>defpkg.CheckServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CheckServlet</servlet-name>
<url-pattern>/CheckServlet</url-pattern>
</servlet-mapping>
The browser URL -
http://localhost:8080/MyApp/CheckServlet
Now if I have to make a call to foo() from the browser, is it possible and if yes, how?
Kind Regards.
No this is not possible! If it was possible it would be a great security hole as a user of your webapp may call any method!
But your servlet may call want it wants in it's lifecycle methods.
The servlet spec (2.5) only supports the following;
doGet
doPost
doPut
doDelete
doHead
doOptions
doTrace
No, but you can pass in some parameters through either a GET or a POST, The first one would be the name of the action you want to execute and the other ones would be the parameters to pass in. On the Servlet side you would map the different actions to different methods and simply pass in the request parameters.
Yes the browser can call in case the web-app is servlet 2.5, The new servlet spec supports custom methods, means the servlet can have doFoo() method, and the browser can call with foo method like any normal GET, POST Http method.
Related
I'm trying to call a method from my server side whose signature is
public Integer method()
but when I redid all the steps used on the StockWatcher tutorial to call it, I'm getting a 404 error which says this is the URL
<p>RequestURI=/com.medtronic.empattendance.EmployeeAttendance/empQueries</p>
I'm not sure what the correct URL should be, but this is the incorrect URL.
my web.xml says this on servlets
<servlet>
<servlet-name>empQueryServerImpl</servlet-name>
<servlet-class>com.medtronic.empattendance.server.EmpQueryServerImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>empQueryServerImpl</servlet-name>
<url-pattern>/empattendance/empQueries</url-pattern>
</servlet-mapping>
Where am I going wrong?
There is an alternative: Use the #RemoteServiceRelativePath (javadoc) annotation on your RPC class (The interface extending RemoteService, not the Async one).
Assuming your GWT app is /empattendance:
#RemoteServiceRelativePath("empQueries")
public interface EmpQueryServer extends RemoteService {
// your methods
}
I have solved it:
I had <url-pattern>/empattendance/empQueries</url-pattern> which was based off the tutorial, but digging deeper I found out I needed to use the full package name.
<url-pattern>/com.myCompany.empattendance.EmployeeAttendance/empQueries</url-pattern>
I trying to do two things at once and I don't seem to find answers that can do both.
I'm trying this:
I want URLs ending in /user/{parameter} to be mapped to a JSP page user.jsp where I can access the parameter.
I find ways to pass parameters from the web.xml file to the JSP using this method
<init-param>
<param-name>someParam</param-name>
<param-value>itsValue</param-value>
</init-param>
And I find ways to create URL filters and map them to Java Servlets.
What I need is a combination. Also, what I found on passing URL parameters to Servlets wasn't too detailed either, so a good reference on that would also be more than welcome!
I want URLs ending in /user/{parameter} to be mapped to a JSP page user.jsp where I can access the parameter.
Map a servlet on /user/* and use HttpServletRequest#getPathInfo() to extract the path info.
E.g.
#WebServlet("/user/*")
public class UserServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String pathInfo = request.getPathInfo(); // "/{parameter}"
// ...
request.getRequestDispatcher("/WEB-INF/user.jsp").forward(request, response);
}
}
That's basically all. Use the usual String methods like substring() and/or split() to break down the path info in usable parts.
Use a base-url servlet to parse the URL and perform a conditional servlet forwarding to the appropriate JSP.
request.getRequestDispatcher().forward(JSPurl)
Let us say you have a URL branch /sales/. Under this URL branch, you would allow the following URLs to to be serviced by /implemented/usersales.jsp :
/sales/liquour/users/{region}
/sales/liquour/soft/users/{region}
/sales/toiletries/users/{type}
and the following URLs to be serviced by /implemented/products.jsp
- /sales/groceries/products/{section}
- /sales/groceries/meat/products/{region}
- /sales/groceries/vegetables/beans/products/{region}
You would have a web.xml servlet mapping for servlet class org.myorg.SalesHandler to be mapped to /sales/.
In the service method override in org.myorg.SalesHandler servlet class,
analyse the URL pattern (using regexp or otherwise) and then conditionally forward the request using
request.getRequestDispatcher().forward(JSPurl)
JAX-RS
But why would you do that when we have jax-rs?
How to forward from a JAX-RS service to JSP?.
JAX-RS may seem daunting at first, but it is actually very simple and intuitive to implement.
I am fairly new to servlets and the way I am handling repsonses from the client is using if uri matches a certain path such as:
public class EntryServlet extends HttpServlet
{
public void doGet (HttpServletRequest request, HttpServletResponse response)
throws IOException
{
String uri = request.getRequestURI ();
if (uri.matches ("/1")) {
do something....
} else if (uri.matches ("/2")) {
do something else.....
} else {
throw error message...
}
}
}
This works only if my web service have a few pages. But say i have 50 xml documents and I want to map exmaple.com/1 to a xml ...to example.com/50 to another xml. Now it would be bad design to have 50 if else statements to handle each of the resource. What is a better way to implement this? I am trying to do this purely in java with no third party apps/plugins/frameworks
Update:
I am working with only one servlet with a background thread. Essentially a client request to process a file and the background thread handles the processing and stores xml docs in a db. And I want have each of the xml docs to be a resource on the web service.
You gave the answer "I want to map", so lets use a Map
you have 2 options (that i see now)
1: you put the "/1" as a key and put a String as value that map's to your xyz.xml
2: you put the "/1" as a key and put an object that implements an "Executor" interface...
in both cases you lookup the value for the key and then use the value object to return something useful.
Put this in the init of your Servlet and fill it with your objects:
Map<String,String> myActions = new HashMap<String,String>();
myActions.put("/1","one.xml");
.....
Now you can do this:
String uri = request.getRequestURI ();
if (myActions.containsKey(uri)) {
String value = myActions.get(uri);
do something with value
} else {
throw error message...
}
you can easily change this to option 2 by using object that implement this:
public interface Action {
String execute(HttpServletRequest req, HttpServletResponse res) throws ServletException,
IOException;
}
The answer may depend on what you want to do with the information in the URI. When writing a REST style application, the URI is one of the primary ways that information is passed to your application. So if you may want to re-consider your aversion to additional packages since the REST APIs are very popular for good reason.
Sticking with plain Servlets, lets say we have 50 xml documents that we want to serve based on which id number is passed through the URL.
We could store a table in a database that indicates the correspondence between id number and document. Or we could store this data into a CSV file. Either way, for such a relatively small table, I would just load the whole table into memory when the Servlet starts up. You can place code in an init() method for loading data into your application.
Then we have something like this:
static HashMap<Integer, String> fileMap;
public void init() {
fileMap = new HashMap<> ();
fileMap.put(1,"thing1.xml");
fileMap.put(2,"thing2.xml");
fileMap.put(3,"Otherthingy.xml");
}
Now you can write much cleaner code in your doGet method.
public void doGet (HttpServletRequest request, HttpServletResponse response)
throws IOException {
String uri = request.getRequestURI();
int slash = uri.indexOf("/");
if(slash+1 == uri.length())
//throw an error
String idString = request.getRequestURI().substring(slash+1);
int id = Integer.parseInt(idString);
//should put this in a try catch block and throw an error if it is not a number.
String requestedFile = fileMap.get(id);
if(requestedFile == null)
//throw some error.
// Do whatever you need to do with the file.
}
You should
Move each URI specific logic into a different servlet.
Use the servlet mapping concept from Java Servlet Specification and define the following in your web.xml
<!- Define the servlets here, ofcourse you should use meaningful names -->
<servlet>
<servlet-name>servlet-1</servlet-name>
<servlet-class>com.vikdor.webapps.ServletForURI1</servlet-class>
</servlet>
<servlet>
<servlet-name>servlet-2</servlet-name>
<servlet-class>com.vikdor.webapps.ServletForURI2</servlet-class>
</servlet>
....
<!- Map the servlet to the URL pattern -->
<servlet-mapping>
<servlet-name>servlet-1</servlet-name>
<url-pattern>/1/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>servlet-2</servlet-name>
<url-pattern>/2/</url-pattern>
</servlet-mapping>
....
This will push the routing logic to web.xml and each servlet does a specific job.
Use a framework. That's what they're for. I'm partial to Spring MVC but for a basic use case like this anything modern should be fine. It might feel like a pain to first get it setup but once it's configured development is much faster and much more maintainable.
Edit: I just noticed the original question says not to use any frameworks/libraries. I still stick by this answer though as the majority of the time that's a bad idea. If you really have to then you can create Maps as suggested by a few other people but in the long run it's not maintainable so avoid it while you can.
You can specify in your web.xml uri patterns to route to specific servlet classes. Forgive my bad servlet names.
<servlet>
<servlet-name>processUserXml</servlet-name>
<servlet-class>com.example.server.ProcessUserXml</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>processUserXml</servlet-name>
<url-pattern>/processuser</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>processItemXml</servlet-name>
<servlet-class>com.example.server.ProcessItemXml</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>processItemXml</servlet-name>
<url-pattern>/processitem</url-pattern>
</servlet-mapping>
So instead of accepting uri requests from a single gateway and routing them through if statements (as you're doing now), when a user calls a specific uri, it'll get routed to the appropriate servlet class for you. So calling uri /processuser will route the call to the ProcessUserXml servlet class doGet method (or doPost, if it's defined and that's how the user made the HTTP call).
I have a desktop application from where a client can add a new user, can chat with other user etc... I have 2 options now:
To make a handler servlet which will get post request on
according to request the handler servlet will call required
servlet(e.g loginServlet, chatServlet , addUserServlet etc)
Directly call the required servlet from client e.g make direct
request to chatServlet for chat, login and addUser
Remember my client side is a desktop application. Which method is good for implementing and future enhancements.
Thank you
Well,I think you should go with the 1 st Approach by using Front Controller pattern.
It should consist of only a SINGLE SERVLET which provides a centralized entry point for all requests.This servlet will delegate all request to the required servlet.
You need to do only following thing to apply the front controller pattern in your application:
<servlet>
<servlet-name>////servlet name: FrontController</servlet-name>
<servlet-class>////Fully qualified servlet name e.g: org.chat.controller.FrontController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FrontController<servlet-name>
<url-pattern>/*</url-pattern>
<servlet-mapping>
I couldn't clearly understand your problem from the question. But I would suggest you would start with approach 2 and start implement.
If you face any specific problems then post here.
How do i specify a redirection to another servlet, in the doPost() method of a servlet.
at the moment I'm using
request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
which is wrong since, my parameters in the doGet() method of products are not being called and initialized.
So I'm left with an empty products page after logging in :/
You need to use HttpServletResponse#sendRedirect() to send a redirect. Assuming that the servlet is mapped on an URL pattern of /products:
response.sendRedirect("/products");
This way the webbrowser will be instructed to fire a new HTTP GET request on the given URL and thus the doGet() method of the servlet instance will be called where you can in turn load the products and forward to a JSP which displays them the usual way.
In your doPost you can always call:
return doGet(request, response);