For example, I have a superclass like below
public abstract class SuperServlet extends HttpServlet {
#Resource(name = "varA")
protected static String varA;
}
And the subclass
public class SubServlet extends SuperServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
System.out.println("varA: " + varA);
}
}
I was planned to see the varA's value that I have set in the web.xml, but instead the value I got is null. So I think the resource annotation won't work in a scenario of inheritance like this.
Does anyone know how to make those annotation works on this?
found it. I cannot use it on a static variable because the injection doesn't apply to a field that belong to the class, need to be a individual object.
Related
I observe a very strange behavior of method reference. We have a web app and chain of servlet hierarchy: Servlet A extends Servlet B extends HttpServlet (let's overlooked why do we need this).
The web app is hosting under Tomcat/Java 8 (web.xml version="3.1" metadata-complete="true").
At my local laptop (Tomcat 8.0.35 or 8.5.15, Java 8 Update 131, OSX) I observe stack overflow for such servlet code:
public class A extends B {
#Override
protected void service(HttpServletRequest pRequest, HttpServletResponse pResponse) throws ServletException, IOException {
ServletCommon.servletServiceWrapper(pRequest, pResponse, super::service);
}
}
The stack overflow (see below) looks very suspicious - it doesn't contain class B in the hierarchy at all! Class A calls HttpServlet directly (Why!? And how this even possible!!!????).
At the same time code with lambda works fine:
public class A extends B {
#Override
protected void service(HttpServletRequest pRequest, HttpServletResponse pResponse) throws ServletException, IOException {
ServletCommon.servletServiceWrapper(pRequest, pResponse, (t, u) -> super.service(t, u));
}
}
The wrapper also contains very simple code:
public class ServletCommon {
#FunctionalInterface
public interface MyBiConsumer<T, U>{
void accept(T t, U u) throws ServletException, IOException ;
}
public static void servletServiceWrapper(HttpServletRequest request, HttpServletResponse response,
MyBiConsumer<HttpServletRequest, HttpServletResponse> pDelegate) throws ServletException, IOException {
pDelegate.accept(request, response);
}
}
Stack trace
java.lang.StackOverflowError
ServletA.lambda$service$0(ServletA.java:19)
ServletCommon.servletServiceWrapper(ServletCommon.java:31)
ServletA.service(ServletA.java:19)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
ServletA.lambda$service$0(ServletA.java:19)
ServletCommon.servletServiceWrapper(ServletCommon.java:31)
ServletA.service(ServletA.java:19)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
...
Any ideas?
Pretty much, yeah.
You're managing to call the wrong service() method (the public one with ServletRequest, not the protected one with HttpServletRequest), resulting in an infinite loop. However your example code isn't clear enough to indicate why that's happening.
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.
In my RPCServlet I am using the method AbstractRemoteServiceServlet.getThreadLocalRequest() to get the HttpSession. Now I want to unit-test it. I am using Mockito and thought I just could mock everything, but the method is final and protected.
Is there any other way to Unit-test AbstractRemoteServiceServlet.getThreadLocalRequest().getSession()
At the end you are trying to get a Session. In our case we solve this situation doing this:
Using GUICE for getting our instances (making them available in the GIVEN part of the test)
public class TestServerModule extends com.google.inject.AbstractModule {
#Override
protected void configure() {
.....
bind(HttpServletRequest.class).to(MockRequest.class).in(Singleton.class);
bind(HttpServletResponse.class).to(MockResponse.class).in(Singleton.class);
....
}
....
#Provides
#Singleton
RequestUtil getRequestUtil(final HttpServletRequest req, final HttpServletResponse resp) {
return new RequestUtilsImpl() {
public HttpServletRequest getThreadRequest() {
return req;
}
public HttpServletResponse getThreadResponse() {
return resp;
}
};
}
RequestUitl object contains everything related with Session and more server stuff (that is not important for your problem :D). The important part here is you can have access to the getThreadRequest(), so you have access to getSession() method.
What is the problem? You can not have a real HttpServletRequest object in your instances, so you need to mock them. For doing it, we specified the bind rules at the top.
At the end your test should be something like:
#RunWith(...)
#GuiceModules({TestServerModule.class, ....})
public class YourTest extends junit.framework.TestCase {
#Inject RequestUtil requestUtil;
....
#Test public void
test_session_after_doing_something() {
//GIVEN
HttpSession mockedSession = requestUtil.getThreadRequest().getSession();
....
}
....
}
//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.
This question already has answers here:
When to use Stateful session bean over Stateless session bean?
(2 answers)
Closed 8 years ago.
I'm new to EJB, and I'm trying to understand the diference between Stateless and Stateful bean, so I made a simple example to test them.
#Stateless
public class Service {
private int num;
public Service(){
}
public int getNum() {
return num;
}
public void setNum() {
this.num++;
}
}
#WebServlet("/Controller1")
public class Controller1 extends HttpServlet {
#EJB
private Service serv;
public Controller1() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
serv.setNum();
response.getWriter().println(serv.getNum());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
And the Stateful equivalent:
#Stateful
public class ServiceStateful implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private int num;
public ServiceStateful(){
}
public int getNum() {
return num;
}
public void setNum() {
this.num++;
}
}
#WebServlet("/Controller")
public class Controller extends HttpServlet {
private static final long serialVersionUID = 1L;
#EJB
private ServiceStateful serv;
public Controller() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
serv.setNum();
response.getWriter().println(serv.getNum());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
Both examples act exactly the same, which is surprising for me. Can someone please explain what is the deal here?
Your first example returns the previously set number by chance only : the get method could have been invoked on a different bean instance. It just happened to use the same instance in this particular case, but you can't count on it.
The second one is guaranteed to return you the previously set number, provided another request doesn't call the set method before the get method is called. A stateful bean should not be injected into a servlet.
You can use instance variables of a stateless session bean, but they're not guaranteed to be preserved across method calls. If both approaches behave the same, it simply means you're probably getting the same stateless session bean instance across method calls within the same session.
You are not supposed to have member fields (aka state) in a stateless session bean. For a stateful session bean it's ok. That's the difference.
A stateful bean maintain it initial state during the conversation with the client (on or many).
A Stateless bean state can be changed (it attributes) during the conversation with the client (doesn't affect other clients)
you can see the difference if you execute multiple times!!