How create mock Attribute of ServletContext? - java

I have Servlet which add users in database. Servlet use instance of module for work with database he's alias DBJoint. And Servlet get instance of DBJoint from ServletContext.
#WebListener
public class ContextListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
final ServletContext servletContext =
servletContextEvent.getServletContext();
final DBJoint joint = new DBJointHandler(
"database_scripts",
"authentication_database");
servletContext.setAttribute("db", joint);
}
}
And in each Servlet when I need work with database I call ServletContext and get DBJoint by key "db".
public class AddUserServlet extends HttpServlet {
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("UTF8");
try {
final boolean success = addUserInDatabase(req);
if (success) req.setAttribute("serverAnswer", EDIT_SUCCESS.get());
else req.setAttribute("serverAnswer", ERR_UNIQUE_L_P.get());
req.getRequestDispatcher(ANSWER.get())
.forward(req, resp);
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* Addition user in database.
*
* #return true if addition success, else false.
*/
private boolean addUserInDatabase(final HttpServletRequest req)
throws SQLException {
final User user = getUserFromRequest(req);
return getDatabaseExecutor().addUserAndGetSuccess(user);
}
/**
* Extracts user's data from HttpServletRequest.
*
* #return user from request.
*/
private User getUserFromRequest(final HttpServletRequest req) {
return new User(
req.getParameter("name"),
req.getParameter("login"),
req.getParameter("password"),
req.getParameter("email"),
req.getParameter("role")
);
}
/**
* Get executor database requests.
*/
private ScriptExecutor getDatabaseExecutor() throws SQLException {
final DBJoint db = (DBJoint) getServletContext().getAttribute("db");
return db.getDBScriptExecutor();
}
}
I need test my Servlet, and use mock object instead original object:
In this test I try verify what body doPost call addUser(User u) in executor of database script. But get NPE.
#Test
public void whenUserAddThenAddUserCall() throws ServletException, IOException, SQLException {
final AddUserServlet servlet = new AddUserServlet();
//mock http.
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
User user = new User("name", "login", "password", "email");
//mock database.
ScriptExecutor executor = mock(ScriptExecutor.class);
DBJoint joint = mock(DBJointHandler.class);
when(joint.getDBScriptExecutor()).thenReturn(executor);
final ServletContext context = request.getServletContext();
//In this place I get NPE but why?
context.setAttribute("db", joint);
servlet.doPost(request, response);
verify(executor).addUser(user);
}
Why I have NullPointerException? How test this class? Thank You!

you need to include these as well
ServletContext context = mock(ServletContext .class)
when(request.getServletContext()).thenReturn(context );

You are calling request.getServletContext() on the request object which is a mock.
Mocked objects do no provide real method implementations. Instead of the real getServletContext() implementation, a stubbed version of the method is called returning null.
A mock should be told what it needs to return when a method is called on it, you need to define behavior just like you did for the DBJoinHandler mock.
To solve the NPE, do something like this:
when(request.getServletContext()).thenReturn(context);
where context could be a ServletContext mock.

Related

java servlet test with different URLs

I want to test my Servlet with different incoming URLs. I tried to use Mockito to test if specific function was called:
package servlet;
import blabla;
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration(locations = {"classpath:application-context-test.xml"})
public class MainServletTest extends TestCase{
#Autowired
private Categories categories;
private MockHttpServletRequest request = new MockHttpServletRequest();
#Mock
private HttpServletResponse response;
#Mock
private HttpSession session;
#Mock
private RequestDispatcher rd;
#Test
public void testCategories() throws ServletException, IOException {
// given
request.setServerName("localhost");//here I try to change incoming URL
request.setRequestURI("/test/categories");//here I try to change incoming URL
HttpServletRequest req = spy(request);//???
//when
new MainServlet().doGet(req, response);
//then
verify(req).setAttribute("categories", categories.getContainer());//here try to check if this method is called
}
}
Here I try to change incoming url and check if specific attribute was set for incoming request. Since req is not Mock object but MockHttpServletRequest object - this code does not work. Any ideas?
Either use a mock:
// ...
#Mock
private HttpServletRequest request;
// ...
#Test
public void testCategories() throws ServletException, IOException {
// given
when(request.getServerName()).thenReturn("localhost");
when(request.getRequestURI()).thenReturn("/test/categories")
//when
new MainServlet().doGet(req, response);
//then
verify(req).setAttribute("categories", categories.getContainer());
or
Use MockHttpServletRequest to check the attribute named categories:
assertEquals(categories.getContainer(), req.getAttributes("categories"));

How can I put an object (definied into a servlet) into a session to use it into a JSP page?

this is my first time that I work on a J2EE project and I have the following problem:
I have the following servlet that implement the HttpServlet interface.
public class Salwf extends HttpServlet {
private String msg = StringUtils.EMPTY;
public void init(ServletConfig config) throws ServletException {
super.init(config);
StandardConfigurationFactory standardConfigurationFactory = new StandardConfigurationFactory();
try {
standardConfigurationFactory.init();
} catch (ConfigurationException e) {
throw new ServletException(e);
}
ConfigurationFactory.setInstance(standardConfigurationFactory);
}
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
LoggerMDC.setup(req, res);
Logger logger = (Logger) Logger.getStdLogger(Monitoraggio.class); // do not declare 'logger' as static field in order to work with MDC
String service = req.getParameter("serv");
char serviceId = Utility.getServizio(req.getParameter("serv"));
// The collection that have to be shown in a table inside the JSP view:
SalDettaglio[] salDettaglio = this.getSalDettaglioList();
gotoPage(ConfigurationFactory.getPropertiesPages().getProperty("pagina_salwf"), req, res);
//String paginaDaLanciare = lanciaServizio(serviceId, req, res);
}
/*
private String lanciaServizio(char num_servizio, HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
Logger logger = (Logger) Logger.getStdLogger(Monitoraggio.class); // do not declare 'logger' as static field in order to work with MDC
HttpSession session;
}
*/
private void gotoPage(String address, HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
Logger logger = (Logger) Logger.getStdLogger(Monitoraggio.class); // do not declare 'logger' as static field in order to work with MDC
logger.debug("gotoPage() | address: " + address);
ServletContext ctx = getServletConfig().getServletContext();
RequestDispatcher dispatcher = ctx.getRequestDispatcher(address);
dispatcher.forward(req, res);
}
private SalDettaglio[] getSalDettaglioList(){
SalDettaglio[] salDettaglioArrayResult;
List<SalDettaglio> salDettaglioList = new ArrayList<SalDettaglio>();
List<RM> rmList = new ArrayList<RM>();
RM rm1 = new RM("codiceRM1", "Andrea", "01/01/1014", "acqRiserva1", "consegnaFinale1", "descrizioneRM1", BigDecimal.valueOf(1000));
RM rm2 = new RM("codiceRM2", "Andrea", "01/01/1014", "acqRiserva2", "consegnaFinale2", "descrizioneRM2", BigDecimal.valueOf(1000));
rmList.add(rm1);
rmList.add(rm2);
RM[] rmArray = (RM[]) rmList.toArray();
SalDettaglio salDettaglio1 = new SalDettaglio("codice1", "stato1", "01/01/2014", "01/06/2014", "Andrea",
"Andrea", "Andrea", BigDecimal.valueOf(1000), "fornitore1",
"rmConRiserva1", "errore1", null, rmArray);
SalDettaglio salDettaglio2 = new SalDettaglio("codice2", "stato2", "01/01/2014", "01/06/2014", "Andrea",
"Andrea", "Andrea", BigDecimal.valueOf(1000), "fornitore2",
"rmConRiserva2", "errore2", null, rmArray);
salDettaglioList.add(salDettaglio1);
salDettaglioList.add(salDettaglio2);
salDettaglioArrayResult = (SalDettaglio[]) salDettaglioList.toArray();
return salDettaglioArrayResult;
}
}
As you can see into the service() method I have this array definition:
SalDettaglio[] salDettaglio
Now I have to put it into session so that I can use it into a JSP view.
How can I do it?
HttpSession session = req.getSession();
session.setAttribute("salDettaglio", salDettaglio);
This puts salDettaglio in the session and you can acces it with the attribute identifier salDettaglio keep in mind that it stores it as a plain Object so you'll have to cast in in the JSP if you are using sciplets.
Also see this question
Beware that Session's getAttribute / setAttribute methods are synchronized, but what you store with them is your responsibility. That means if you change a mutable field in the stored object that is not guaranteed to be seen by another thread. Since servlets are called by different threads from a thread-pool this can be a problem. To avoid this use either immutable objects or make your objects thread-safe.
create one session object and put your array into that session object and using sendRedirect() you can fwd your session through it..!!

Servlet filter "returning" an object for later use

I'm implementing security in my RESTful webservice, and I'm thinking of creating a filter that checks if the Authorization header is valid or not, and this check is done by sending the token to a third party endpoint. If the token is valid, the third party endpoint has to send me a response that contains information regarding the token's expiration, client id, scope, and other stuff. The logic, then, is this:
#Override
public void doFilter(
final ServletRequest request,
final ServletResponse response,
final FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
header = req.getHeader("Authorization");
EndpointResponse eResponse = Endpoint.validate(header);
if(eResponse.valid())){
chain.doFilter(...);
return eResponse; //or equivalent
}else{
HttpServletResponse res = HttpServletResponse(response);
res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
...
}
}
Then, in a DAO class, I will use the eResponse like this
public final class DAO{
public void checks(){
if(eResponse.scope() == "ADMIN"){
...
}else{
...
}
}
}
Is there a way to inject or return an object after the filter does the validation? Hopefully, without using spring or hibernate, since I can't use these at my job.
-EDIT-
The way I'm accessing the DAO would be like this
#Path("")
public class CertificationService {
#GET
#Produces(CertificationApplication.SUPPORTED_REPRESENTATIONS)
#Path(CertificationConstants.URL_PATH)
public Response getCertificationByUpId(String upId) throws CertificationException {
ResponseBuilder response;
try{
response = Response.ok(DAO.findCertificationByUPID(upId));
} catch (CertificationException e) {
response = handleException(e);
}
return response.build();
}
}
The findCertificationByUPID method would have to call the checks() method I declared above.
Try placing the object on the request using setAttribute():
request.setAttribute("auth", eResponse);
Then your controller can grab the object using
EndpointResponse eResponse = (EndpointResponse) request.getAttribute("auth");
and do whatever you like with it (including passing it to the DAO):
dao.checks(eResponse);
where DAO is like what you have above, but with
public void checks(EndpointResponse eResponse) { ... }
instead.
If you prefer to keep the EndpointResponse out of the DAO, you can do
public void checks(String role) { ... }
or similar.

Get status of handling request by Spring's ResourceHttpRequestHandler.handleRequest() method

I have the code like:
#PostConstruct
public void init() throws IOException {
resourceHttpRequestHandler = new ResourceHttpRequestHandler();
resourceHttpRequestHandler.setServletContext(servletContext);
resourceHttpRequestHandler.setLocations(... my locations here... );
}
#RequestMapping(value = "/mypath/**", method = RequestMethod.GET)
public void getResource(HttpServletRequest request, HttpServletResponse response) throws Exception {
resourceHttpRequestHandler.handleRequest(request, response);
/* here */
}
Is it possible to know if the resolving of resource request was successful or not (after the call of method handleRequest() )?

Generating a Faces Context manually

I have two systems I'm trying to integrate. One is built on raw servlets, the new one is build on JSF with IceFaces. I'm trying to facilitate cross-system sign on. The idea is that I have a button in the old system that POSTs the appropriate information to the new site and logs them on.
Well, ideally, I'd like to use just a regular old servlet to facilitate that on the new site. Go to the new site's Servlet, do what it needs to do and the forward onto the dashboard.
Our security is handled via a managed bean. However, by the time you get to the Servlet, there is no faces context. So, how would I create a new faces context?
I have a back up plan in that I can always link to a dummy .iface page which will create the FacesContext for me and then create a backing bean that will do stuff when it gets instanciated and then forward onto the main page. But this feels very much like a hack.
Any help would be appreciated!
EDIT: I went with the back up way. Basically, I POST to a page like so:
<f:view>
<ice:outputText value="#{EntryPoint}"/>
</f:view
The backing bean looking like so...
public EntryPoint() {
try {
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
String loginID = request.getParameter("loginID");
//Do some code to load the user/permissions
response.sendRedirect(
//The appropriate page
);
} catch (IOException ex) {
logger.error(null, ex);
} catch (SQLException ex) {
logger.error(null, ex);
}
}
This still feels like a hack, but I'm not sure how to get around this. Ideally, I'd POST to a servlet, get the loginID, build the user and put it directly into the managed bean. But, the FacesContext does not exist at that point.
Any other ideas?
I'm not sure what you mean by "site" in this context.
A couple of notes:
Managed beans will be never be available outside the web app (WAR) in which they are defined.
FacesContext object instances are ultimately created and disposed by FacesServlet.service, so requests should pass through this servlet. Attempting to create a context under other circumstances might lead to undefined behaviour.
Bearing that in mind, you could create a request sequence like this:
FacesServlet (mapping: /faces/*)
-> /faces/jsfPage.jsp (a JSP with JSF controls)
-> DispatchBean (calls ExternalContext.dispatch("/AnotherServlet")
-> AnotherServlet
jsfPage.jsp contains:
<f:view>
<h:outputText value="#{dispatchBean.dispatch}" />
</f:view>
The "dispatch" property resolves to a bean method "getDispatch":
public String getDispatch() {
FacesContext context = FacesContext.getCurrentInstance();
try {
context.getExternalContext().dispatch("/FacesClientServlet");
} catch (IOException e) {
throw new FacesException(e);
}
return null;
}
Which dispatches to this servlet:
public class FacesClientServlet extends javax.servlet.http.HttpServlet
implements javax.servlet.Servlet {
static final long serialVersionUID = 1L;
#Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
FacesContext context = FacesContext.getCurrentInstance();
ELContext elContext = context.getELContext();
ExpressionFactory expressionFactory = context.getApplication()
.getExpressionFactory();
ValueExpression expression = expressionFactory.createValueExpression(
elContext, "#{myBean.text}", Object.class);
Object value = expression.getValue(elContext);
ResponseWriter writer = context.getResponseWriter();
writer.write("" + value);
}
}
Which emits the value from a managed bean "myBean":
public class MyBean {
private final String text = "Hello, World!";
public String getText() {
return text;
}
}
This is all very convoluted and I wouldn't willingly do any of it.
An alternative, which may come with its own consequences, is to create your own context like this:
public class ContextServlet extends javax.servlet.http.HttpServlet implements
javax.servlet.Servlet {
static final long serialVersionUID = 1L;
private FacesContextFactory facesContextFactory;
private Lifecycle lifecycle;
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
facesContextFactory = (FacesContextFactory) FactoryFinder
.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
lifecycle = lifecycleFactory
.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
}
#Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
FacesContext context = facesContextFactory.getFacesContext(
getServletContext(), request, response, lifecycle);
try {
ELContext elContext = context.getELContext();
ExpressionFactory expressionFactory = context.getApplication()
.getExpressionFactory();
ValueExpression expression = expressionFactory
.createValueExpression(elContext, "#{myBean.text}",
Object.class);
Object value = expression.getValue(elContext);
PrintWriter pw = response.getWriter();
try {
pw.write("" + value);
} finally {
pw.close();
}
} finally {
context.release();
}
}
}
Again, I would avoid this approach if possible.

Categories