Cannot run simple servlet with use of annotations - java

I am new java programmer. So I do understand the process of running servlet through mapping etc in the web.xml and I also can launch the servlet through annotation, my question is when I use the annotation, and run the project on the server, why do I have to write the serlvet name in the URL after project name for it to launch.
Is there any way without using web.xml file at all, giving an annotation and then when I run project on server that it would automatically launch and run the servlet? Instead of my writing the servlet name and hitting enter for it to launch.
#WebServlet(urlPatterns = {"/GetDate"})
public class GetDate extends HttpServlet{
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Date date =new Date();
resp.setContentType("text/html");//this says we will send back html type
//get a pen to write back
PrintWriter pen=resp.getWriter();
//write back
pen.write(date.toString());
}
}
I would like the above simple servlet to just launch automatically as soon as I select run on server from eclipse.

You can specify load on startup in annotation, then the servlet's init() method is invoked when the web server starts
#WebServlet(urlPatterns = {"/GetDate"}, loadOnStartup=1)
public class GetDate extends HttpServlet{
#Override
public void init() throws ServletException {
// do some init stuff
}

It's all in the #WebServlet notation. If you change your code to be:
#WebServlet(urlPatterns = {"/"})
public class GetDate extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Date date =new Date();
resp.setContentType("text/html");//this says we will send back html type
//get a pen to write back
PrintWriter pen=resp.getWriter();
//write back
pen.write(date.toString());
}
}
Then the servlet is served at the / URL (after your webapplication name)
Be careful doing this. Traditionally you serve HTML resources from the / location. If you take this over with your servlet then you can't serve HTML. Additionally if you have more than one servlet then which one gets the / path - where do the rest go? It can be a bit self documenting to have the URL match the servlet. Note that there is no need to keep it the same name as the servlet - call it /myBigLongURLMapping if you like - the name is up to you.

Instead of #WebServlet(urlPatterns = {"/GetDate"}) write like this #WebServlet("/GetDate")
#WebServlet("/GetDate")
public class GetDate extends HttpServlet{
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Date date =new Date();
resp.setContentType("text/html");//this says we will send back html type
//get a pen to write back
PrintWriter pen=resp.getWriter();
//write back
pen.write(date.toString());
}
}

Related

Set default servlet

I tried to set default servlet by this way:
#WebServlet({"/abc", "","/"})
public class GreetingServlet extends HttpServlet {
#Override
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
getServletContext().getRequestDispatcher("/asd/ind.html").forward(request,response);
}
#Override
public String getServletInfo() {
return "The Hello servlet says hello.";
}
}
The file /asd/ind.html is exist, when I remove "/" like :
#WebServlet({"/abc", ""})
the redirection works fine when I hit:
contextpath/abc
contextpath/
contextpath
But with "/" like
#WebServlet({"/abc", "","/"})
It turns out
javax.servlet.ServletException: AS-WEB-CORE-00089
When I hit any URL at all, even the previous ones that did work.
Could anyone please give me an explanation? the "/" should make the servlet default which means any unmapped URL should redirected to GreetingServlet.
The problem happened because the default servlet maps the URI to the static path if it's not mapped to any servlet, but what I did is redefining the default servlet, so when I redirect to /asd/ind.html and this URI is not mapped to any servlet the default serlvet is called and in this case the default one is GreetingServlet, this causes infinite loop.

How to call Generic Portlet methods from servlet?

I have created a portlet and able all my business logic is performing in a servlet. I need to get the liferay login user details in the servlet. SO I have created a class which will extend the GenericPortlet. Now My question is how can I call that class I need to execute the GenericPorlet unimplemented method. My code is as follows,
public class ActionProcess extends GenericPortlet {
public void init() throws PortletException{
super.init();
}
public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
User user = (User) request.getAttribute(WebKeys.USER);
ThemeDisplay td =(ThemeDisplay)request.getAttribute(WebKeys.THEME_DISPLAY);
User urs = td.getUser();
System.out.println("doView "+ urs);
System.out.println("doView "+ user);
}
}
Now I need to call the doView() and return the values to servlet. How can I do that my servlet code is.
#WebServlet("/demoClass")
public class demoClass extends HttpServlet {
private static final long serialVersionUID = 1L;
public demoClass() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(request, response); //
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//Here I am performing the business logic....
//How do I call the ActionProcess class here, I need to get the User name which is return by diView() method
}
}
Any suggestions?
You can't, and my answer is very similar to my answer to your very similar question.
It's the framework's (portal's) business to call the lifecycle methods of a portlet. Not yours.
You need to rethink your problem and come up with a different architecture. Or give us your problem to suggest a different solution than the one that you're currently pursuing.
Differing from that answer, I'm assuming that in this case you're within the very same same web application (portlet and servlet are deployed in the same webapp). However, just like in that other question, a portlet's request is routed through the portal while the servlet's request is not. You'll not have the data available.

Mocked object to return actual data

//MyServlet.java
public class MyServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, Exception {
int sum = Integer.parseInt(request.getParameter("a")) + Integer.parseInt(request.getParameter("b"));
request.setAttribute("sum",sum);
RequestDispatcher dispatcher=request.getRequestDispatcher("/ShowSum.jsp");
dispatcher.forward(request,response);
}
}
//TestServelt.java
public class TestServelt {
#Test
public void testSum() throws Exception {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
RequestDispatcher dispatcher = mock(RequestDispatcher.class);
when(request.getParameter(a)).thenReturn(10);
when(request.getParameter(b).thenReturn(20);
when(request.getRequestDispatcher(anyString())).thenReturn(dispatcher);
MyServlet testServlet = new MyServlet ();
testServlet.doPost(request, response);
int sum = (int)request.getAttribute("sum"); // here it's will return NULL.
}
}
I am trying to write somewhat similar Test case for a servlet
as u can see , that sum variable can't be mocked cuz that will defeat the purpose , i want it to return what got calculated after the servlet call. can anyone help or give a different approach.
You can't use mock objects in this case; mock objects are just thin API layers, they have no functionality or intelligence.
Use a framework with simulates the Servlet API like mockrunner or the Spring Web testing framework.

Static or nonstatic action in mvc?

i want to ask you about mvc. How it works. So, this is simple example(I don't use any frameworks)
in Controller(Servlet):
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
private void processRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String page = null;
AbstractCommand action;
action = ActionFactory.getAction(request);// get command from factory
page = action.execute(request, response);
RequestDispatcher dispatcher = getServletContext()
.getRequestDispatcher(page);
dispatcher.forward(request, response);
}
for action we create a common interface(Strategy pattern):
public interface AbstractAction {
public String execute(HttpServletRequest request, HttpServletResponse response);
}
Simple Action(Example):
public class HelloAction implements AbstractAction {
#Override
public String execute(HttpServletRequest request,
HttpServletResponse response) {
//....(some actions to modify request)
String page = "/main.jsp";
return page;
}
}
And now, our factory:
public class ActionFactory {
private enum Actions{
HELLO;
}
public static AbstractAction getAction(HttpServletRequest request){
String action = request.getParameter("action");//take parameter from jsp
Actions actionEnum = Actions.valueOf(action.toUpperCase());
switch (actionEnum) {
case HELLO:
return new HelloAction();
}
}
}
We came to the place where I am in confused. Servlet is initialized only once, and only one for all requests. Just forwards requests to the actions where we modify request or response. But, we create NEW instance of the class for every request. Here can occur memory overflow!? Or not?
Can we make these actions static(static method, one for all request)? If two requests come at the same time what will happen to them?
What do you think about this, please share your experience.
P.S. sorry for bad english.
How about Singleton pattern to get the instance of the Action class ?
Just add some abstact getInstance() method in AbstractAction.
Make every implementation provide its own instance.
In every implementation class, use Singleton pattern so that only one instance exists.
Make sure no action class stores any data related to a specific request.
As i understood the jsp, the whole thing is stateless, if u access the servlet by http request, the servlet will be created in a new instance.
After leaving the servlet by .forward(), it will be released by garbage collection.
2,3,...,n requests = 2,3,...,n servlets.
by forwarding to a jsp, the only way to access the servlet from jsp is a new http request = new servlet. ( will move to the doPost method)

Setting ISO-8859-1 encoding for a single Tapestry 4 page in application that is otherwise totally UTF-8

I have a Tapestry application that is serving its page as UTF-8. That is, server responses have header:
Content-type: text/html;charset=UTF-8
Now within this application there is a single page that should be served with ISO-8859-1 encoding. That is, server response should have this header:
Content-type: text/html;charset=ISO-8859-1
How to do this? I don't want to change default encoding for whole application.
Based on google searching I have tried following:
#Meta({ "org.apache.tapestry.output-encoding=ISO-8859-1",
"org.apache.tapestry.response-encoding=ISO-8859-1",
"org.apache.tapestry.template-encoding=ISO-8859-1",
"tapestry.response-encoding=ISO-8859-1"})
abstract class MyPage extends BasePage {
#Override
protected String getOutputEncoding() {
return "ISO-8859-1";
}
}
But neither setting those values with #Meta annotation or overriding getOutputEncoding method works.
I am using Tapestry 4.0.2.
EDIT: I ended up doing this with a Servlet filter with subclassed HttpServletResposeWrapper. The wrapper overrides setContentType() to force required encoding for the response.
Have you considered a Filter? Maybe not as elegant as something within Tapestry, but using a plain Filter, that registers the url mapping(s) of interest. One of its init parameters would be the encoding your after. Example:
public class EncodingFilter implements Filter {
private String encoding;
private FilterConfig filterConfig;
/**
* #see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
public void init(FilterConfig fc) throws ServletException {
this.filterConfig = fc;
this.encoding = filterConfig.getInitParameter("encoding");
}
/**
* #see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
req.setCharacterEncoding(encoding);
chain.doFilter(req, resp);
}
/**
* #see javax.servlet.Filter#destroy()
*/
public void destroy() {
}
}
You could have done:
#Override
public ContentType getResponseContentType() {
return new ContentType("text/html;charset=" + someCharEncoding);
}
The filter suggestion is good. You can also mix servlets with Tapestry. For instance, we have servlets for serving displaying XML documents and dynamically generated Excel files. Just make sure that correctly set the mappings in web.xml so that that the servlets do not go through Tapestry.
Tapestry has the concept of filters that can be applied to the request/response pipeline, but with the advantage that you can access the T5 IoC Container & Services.
http://tapestry.apache.org/tapestry5/tapestry-core/guide/request.html

Categories