writing junit test for specific scenario - java

I am trying to write junit for my java web application which uses older command line design pattern (no framework is used for this older application).
I have a scenario in my application.
When the application is deployed in a server, first the server will find the web.xml and load and run the TestDataServlet(servlet class configured in web.xml which extends http servlet) before everything gets deployed in the server.
This TestDataServlet in turn calls the TestRunnable class which is a thread which loads all the properties file (contans informaton about endpoint everything which is used in java classes of my application code) and intialize it before hitting the application in browser.
I am trying to write junit for this application by using one time step up which loads all the properties file before running my junit, so that I can test it easily.
Since my application is not using a framework, I was not able to do it as spring junit does it.
Since there anyway to do it? Could I able to run the TestDataServlet before running my junit class?
Any help is appreciated.

Modify your TestDataServlet to be able to process a request "isTestRunnableCompleted". Have the return be true or false.
In your JUnit test, implement the setup() method. Call the TestDataServlet to start the runnable. Then, in a while() loop inside the setup() method, every second, call the TestDataServlet to check "isTestRunnableCompleted". If it is "false", sleep for a second, and then allow the loop to make the call again. You may want to implement some sort of a timeout in the loop also just in case things go wrong.
Good luck.
public class TestDataServlet
{
public void doGet( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException
{
// Look for some indicator in the request that the caller wants a "status"
// of the test data being set up
if ( request.getParameter( "isTestDataRunnableCompleted" ) != null )
{
boolean status = testDataRunnableThread.isAlive();
PrintWriter writer = response.getWriter();
writer.println( Boolean.toString( status ) );
writer.close();
}
else
{
// If we get here, then start the test data runnable thread
}
}
}

Related

How do I change only the status code on a Spring MVC error with Boot?

I'm writing a Web application that makes downstream calls using RestTemplate. If the underlying service returns a 401 Unauthorized, I want to also return a 401 to the calling application; the default behavior is to return a 500. I want to keep the default Spring Boot error response as provided by BasicErrorController; the only change I want is to set the status code.
In custom exceptions, I'd just annotate the exception class with #ResponseStatus, but I can't do that here because HttpClientErrorException.Unauthorized is provided by Spring. I tried two approaches with #ControllerAdvice:
#ExceptionHandler(HttpClientErrorException.Unauthorized.class)
#ResponseStatus(UNAUTHORIZED)
public void returnsEmptyBody(HttpClientErrorException.Unauthorized ex) {
}
#ExceptionHandler(HttpClientErrorException.Unauthorized.class)
#ResponseStatus(UNAUTHORIZED)
public void doesNotUseBasicErrorController(HttpClientErrorException.Unauthorized ex) {
throw new RuntimeException(ex);
}
How can I configure MVC to continue to use all of the built-in Boot error handling except for explicitly overriding the status code?
The below code works for me -- in an app consisting of a #RestController whose one method consisted of throw new HttpClientException(HttpStatus.UNAUTHORIZED), running on an embedded Tomcat. If you're running on a non-embedded Tomcat (or, I suspect, on an embedded non-Tomcat) odds are you'll have to do something at least somewhat different, but I hope this answer is at least somewhat helpful anyway.
#ControllerAdvice
public class Advisor {
#ExceptionHandler(HttpClientException.class)
public String handleUnauthorizedFromApi(HttpClientException ex, HttpServletRequest req) {
if (/* ex instanceof HttpClientException.Unauthorized or whatever */) {
req.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, 401);
}
return "forward:/error";
}
}
Explanation: when a HttpClientException is thrown while we're processing request X (in an embedded servlet), what normally happens is that it bubbles all the way up to some org.apache class. (I might fire the debugger up again and work out which one, but this is a pretty high-level explanation so it doesn't matter much.) That class then sends request X back to the application, except this time the request goes to "/error", not to wherever it was originally going. In a Spring Boot app (as long as you don't turn some autoconfiguration off), that means that request X is ultimately processed by some method in BasicErrorController.
OK, so why does this whole system send a 500 to the client unless we do something? Because that org.apache class mentioned above sets something on request X which says "processing this went wrong". It is right to do so: processing request X did, after all, result in an exception which the servlet container had to catch. As far as the container is concerned, the app messed up.
So we want to do a couple of things. First, we want the servlet container to not think we messed up. We achieve this by telling Spring to catch the exception before it reaches the container, ie by writing an #ExceptionHandler method. Second, we want the request to go to "/error" even though we caught the exception. We achieve this by the simple method of sending it there ourselves, via a forward. Third, we want the BasicErrorController to set the correct status and message on the response it sends. It turns out that BasicErrorController (working in tandem with its immediate superclass) looks at an attribute on the request to determine what status code to send to the client. (Figuring this out requires reading the class's source code, but that source code is on github and perfectly readable.) We therefore set that attribute.
EDIT: I got a bit carried away writing this and forgot to mention that I don't think using this code is good practice. It ties you to some implementation details of BasicErrorController, and it's just not the way that the Boot classes are expected to be used. Spring Boot generally assumes that you want it to handle your error completely or not at all; this is a reasonable assumption, too, since piecemeal error handling is generally not a great idea. My recommendation to you -- even if the code above (or something like it) does wind up working -- is to write an #ExceptionHandler that handles the error completely, meaning it sets both status and response body and doesn't forward to anything.
You can customize the error handler of the RestTemplate to throw your custom exception, and then handle that exception with the #ControllerAdvice as you mentioned.
Something like this:
#Configuration
public class RestConfig {
#Bean
public RestTemplate restTemplate(){
// Build rest template
RestTemplate res = new RestTemplate();
res.setErrorHandler(new MyResponseErrorHandler());
return res;
}
private class MyResponseErrorHandler extends DefaultResponseErrorHandler {
#Override
public void handleError(ClientHttpResponse response) throws IOException {
if (HttpStatus.UNAUTHORIZED.equals(response.getStatusCode())) {
// Throw your custom exception here
}
}
}
}

Spring Boot in standalone Tomcat ignores exceptions set in DeferredResults

I'm running a Spring Boot 1.2.1 application in standalone Tomcat.
I have two controller mappings, which both for simplicity always throw an exception. The first one is for a GET request and it returns a String for the view name:
#RequestMapping(value = {
"/index"
}, method = RequestMethod.GET)
public String init() throws MyRequestProcessingException {
if (true) {
throw new MyRequestProcessingException(
"Something went wrong processing request");
}
return "init";
}
This is the exception definition:
#ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR)
public class MyRequestProcessingException extends Exception {
public MyRequestProcessingException(String message) {
super(message);
}
}
In embedded Tomcat as well as in standalone Tomcat, trying to access /index always results in a 500 with some JSON error data being returned to the client.
My controller has another method which accepts a POST and returns a DeferredResult:
#RequestMapping(value = "html/start", method = RequestMethod.POST, consumes = APPLICATION_FORM_URLENCODED)
public DeferredResult<String> start(final HttpServletResponse response,
#Valid #ModelAttribute final InitialisationStartAttributes model,
final SessionData sessionExisting) throws MyRequestProcessingException {
final DeferredResult<String> finalResult = new DeferredResult<>(5000);
// Just return an error, so we can test
if (true) {
finalResult.setErrorResult(new MyRequestProcessingException(
"Something went wrong processing request"));
}
return finalResult;
}
In embedded Tomcat, a POST to /html/start returns a 500 with some JSON data in the response body, just like the other request method. However, when I try to reproduce this behaviour using a standalone Tomcat instance, I always get a 200 response with no response body.
I'm using Tomcat 8 in embedded and Tomcat 7.0.52 standalone, but I've also tried with standalone Tomcat 8 and it doesn't make a difference.
My application is deployed in the root application context by modifying /etc/tomcat/Catalina/localhost/ROOT.xml.
EDIT: I've done a bit more testing, and it does seem that DeferredResult is the culprit. I have yet to override handleErrorResult() to see what happens. I'm a bit surprised though, because I don't recall seeing anything in the documentation about the difference between returning a DeferredResult in embedded vs standalone Tomcat.
If you throw an exception in a #RequestMapping and don't handle it anywhere, then the response status is not set before you hit the ErrorPageFilter. If you want to map status to error path in your customizer, you need to handle the error and get the status set in the filter chain somewhere (e.g. with an #ExceptionHandler or by using an Exception with a #ResponseStatus). Another way to get your custom error page to render would be to map exceptions instead of (or as well as) the HttpStatus, using new ErrorPage(Exception.class, "/html/error").
This behaviour was due to a bug in Spring Boot's ErrorPageFilter; see bug report on GitHub. It was fixed in Spring Boot 1.2.3.

How to make a servlet respond to multiple requests?

I have a task that I want to wrap in a servlet to provide the ability to run the task remotely, by http request.
I know I can achieve this with REST API, but currently I assume (and please correct me if I'm wrong) that a simple servlet will do.
One of the things I want to achieve is that if a request to the servlet is made while another request is still processed, I'll get an appropriate response - "Task is already running".
I've built a simple servlet, using servlet-3.0, that calls the jar I want to run, but when I make 2 requests, the second one is not processed until the first one is finished.
EDIT:
My servlet is a simple http serlvet. service method overriden.
I have a system.out.println("a") in the start.
when I call the servlet in debug mode and then (while stopped at breakpoint) call it again, the message is printed only one time and printed the second time when I release the breakpoint and the first run finishes.
First of all, this does not seems like REST at all. If you really just want to spawn a (single) background task, make sure you do it in a separate worker thread, not the request thread.
Maybe you need a lock:
public class Task extends HttpServlet {
// for singleton
//private volatile boolean running = false;
// or try this:
public static boolean running = false;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
if(running){
PrintWriter out = response.getWriter();
out.println("running");
return;
}
synchronized(Task.class){
if(!running){
running = true;
// run the task
running = false;
}
}
}
}

Java Servlet POST action not receiving parameters from request

Yesterday I tried using Tomcat and Servlets for the first time (I come from IIS/C#/MVC).
I'm also using AngularJS and Guice.
I've made a Servlet that has a single method:
#Singleton
#SuppressWarnings("serial")
public class CommandServlet extends HttpServlet {
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println(req.getParameterMap());
}
}
I've made a service in Angular that looks like the following:
app.factory('console', [ '$http', function($http) {
var console = {};
console.execute = function(gameId, command) {
$http.post("Command/", {
gameId : gameId,
command : command
}).success(function(data, status, headers, config) {
}).error(function(data, status, headers, config) {
});
};
return console;
} ]);
In my controller I inject the service and expose it to the view via an "execute" function on the scope:
app.controller('PlayController', function($scope, console) {
$scope.consoleIn = "";
$scope.gameId = 1;
$scope.execute = function(command) {
$scope.consoleOut = console.execute($scope.gameId, command);
};
});
And in my view I have a button which calls the function and passes in text from an input element:
<input ng-model="consoleIn" type="text">
<button class="btn" type="button" ng-click="execute(consoleIn)">Go!</button>
For some reason the console on my Tomcat server is printing an empty Map ({}) without the parameters being passed with the POST request. When I look at the network tab in Chrome's Console thingy and see that the parameters are being sent ({"gameId":1,"command":"a"}), so my question is 1) Am I doing the right thing to get the values out of the POST request (getParameterMap() ?) and 2) if I am doing the right thing, what am I doing wrong so that the request my browser makes isn't getting to my servlet properly?
EDIT:
I ended up using Jersey as my container (I think it's called) instead of Java's default Servlets. I did this after seeing Jersey popping up with Guice often on Google, thinking there would be sufficient documentation to get the two of them working together. There are several examples and I sort of drew on several, especially this one.
The snag I ran into getting it to work was this, but now everything's good to go.
Overall I'd say that if you like Guice for your DI and want to make a Java website, Jersey is good. It appears to be for a different more specialized functionality of RESTful services than regular servlets - but that's what I needed, anyway. From my un-scientific Googling observations besides Tomcat there's Grizzly and Jetty that are popular as well - you may want to look into them if you're having trouble with Tomcat.
I hope this edit saves someone the hours I spent yesterday and today getting it to work.
What does it actually print? Some of the Tomcat Map implementations don't print their contents in their toString() method. Try another way of seeing what's in it. You'll find its all there.

What would be the best way to match up two object instances between two different applications in a J2EE server?

I have a J2ee application where I basically want two objects, created by two separate servlets to communicate directly and I need these intances to be stable, i.e. to "know" each other during the session.
The sequence is roughly:
Client sends a request to Servlet #1, which creates object A
Client sends a second request (after the first returns) to servlet #2 which creates object B.
Object B finds A, using JNDI, and the two objects interact.
The client now continues to send requests to object A which needs to find B again.
How do I make sure that these two instances know each throughout the session?
Binding them to JNDI doesn't entirely solve the problem, since object B needs to communicate with its original servlet (servlet #2), which is not kept stable across requests.
Any ideas?
Thanks in advance.
Yes, I admit the problem description is a bit vague. But it's not a very simple application.
Still, I will try to ask it better:
My end goal is to create a sort of a "semantic debugger" for my application that, as opposed to a java debugger which simply debugs the java statements.
The application debugged is basically a servlet. which my tool connects to.
The tool maintains a connection to the application through another servlet which controls the debugging process.
These two servlets need to communicate with each other constantly and directly.
My current thought is to set up a stateful session bean that will facilitate this communication (never done it, still struggling with setting it up).
But I would appreciate any thoughts on how to achieve this better.
And what stops you from using the Session? You don't need JNDI, just place your object into session under a predefined name. If the communication object is application-wide, use Singleton.
P.S. It looks to me you're doing something weird, while the solution could in fact be simpler. Can you describe the task, not the proposed implementation? What is a "semantic debugger" anyway?
To be honest: I don't fully understand what you are trying to achieve.
Can you perhaps try to explain the problem you are trying to solve instead of the solution?
What do these objects depend on? Are they user specific? Then put them into the session and you can retrieve them from the session again (request.getSession().getAttribute("A")).
Are they global for all users? In that case put them into a spring configuration and retrieve them from there.
Never store any information inside the servlet.
EDIT:
ok, so from what I understand storing the values in the session is imho the best way to solve this problem (in "Java-Pseudo-Code"):
public class BusinessServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res) {
HttpSession session = req.getSession(true);
BusinessCode business = session.getAttribute("A");
if (business == null) {
business = new BusinessCode();
session.setAttribute("A", business);
}
DebugObject debug = session.getAttribute("B");
if (debug == null) {
debug = new DebugObject();
session.setAttribute("B", debug);
}
business.doSomeWork(debug);
}
}
public class DebugServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res) {
HttpSession session = req.getSession(true);
DebugObject debug = session.getAttribute("B");
if (debug != null) {
debug.printDebugMessages(res);
}
}
}
Does this help?

Categories