Program hanging at call for REST service - java

I am running a REST service on Tomcat and a client service from Eclipse.
My program keeps stopping when on it's second run through. I am not receiving any exceptions in the console running Tomcat
The first time my Controller is called, there is no issue and everything runs fine. After everything executes in the Controller, the user is redirected back to a JSP page. When a button is clicked on the JSP page, the Controller code shown below is run again.
However this time, the program stops in the function:
getOrderDetails(id, order, service);
while executing the line:
String orderXML = service.path("rest").path("coffee").header("user", "customer-123").accept(MediaType.APPLICATION_XML_TYPE).get(String.class);
This line calls the REST service which will interact with my SQLite database and then return some `XML.
I really cannot work out why it is stopping on the second attempt!
Any help with this would be GREATLY appreciated!
Thank you!
Update 1: If it's of any significance, I find that when the program hangs, I need to not only quit Eclipse and restart it, but I also need to restart the server. Otherwise, the client program won't work properly.
Update 2: I have defined only one ClientResponse to be used at all points in the program.
Update 3: I've been using ClientResponse.close() after each of my requests.
NOTE: Code updated to reflect comment below
Controller:
static ClientConfig config = new DefaultClientConfig();
static Client client = Client.create(config);
static WebResource service = client.resource(getBaseURI());
ClientResponse clientResp;
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 {
// Get All Coffee Orders
clientResp = service.path("rest").path("coffee").header("user", "customer-123").type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).get(ClientResponse.class);
String orderXML = clientResp.getEntity(String.class);
clientResp.close();
try {
Document document = loadXMLFromString(orderXML);
NodeList nodeList = document.getDocumentElement().getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element elem = (Element) node;
CoffeeOrder order = new CoffeeOrder();
// Set ID
String id = elem.getElementsByTagName("id").item(0).getChildNodes().item(0).getNodeValue();
order.setId(id);
// Get ALL Order Details
getOrderDetails(id, order);
// Get ALL Payment Details
getPaymentDetails(id, order);
// If order has not been cancelled, add to open orders
if (!order.getOrderStatus().equals("cancelled")){
openOrders.add(order);
// If order has been cancelled, add to cancelled orders.
} else {
cancelledOrders.add(order);
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/index.jsp");
dispatcher.forward(request, response);
}
// Get all Order Details
private void getOrderDetails(String id, CoffeeOrder order){
// PROGRAM STOPS HERE ON SECOND RUN THROUGH
clientResp = service.path("rest").path("coffee").path(id).header("user", "customer-123").type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).get(ClientResponse.class);
orderXML = clientResp.getEntity(String.class);
clientResp.close();
// Do Things here with XML
} catch (Exception e){
e.printStackTrace();
}
}
// Get all Payment Details
private void getPaymentDetails(String id, CoffeeOrder order){
clientResp = service.path("rest").path("payment").path(id).header("user", "customer-123").type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).get(ClientResponse.class);
orderXML = clientResp.getEntity(String.class);
clientResp.close();
// Do Things here with XML
} catch (Exception e){
e.printStackTrace();
}
}

I finally realised what the problem was...
It had to do with multiple database connections that were being opened on the server side! This was causing the issue and once I dealt with that the problem resolved itself.
Thanks for all your help!

Related

Java servlet not receiving request attributes [duplicate]

This question already has answers here:
Difference between getAttribute() and getParameter()
(10 answers)
Closed 3 years ago.
I'm currently working on a web app in which I want to update the user as to whether or not an operation was successful. I attempt to achieve this by setting request attributes and forwarding from one servlet to the next. However, the attribute is always null in the receiving controller.
code block that sets the attribute:
try {
updateXRef(request, response, cmds);
} catch (Exception e) {
request.setAttribute("results", "Error encountered. Contact system administrator.");
push(request, response);
}
request.setAttribute("results", "Update Successful");
push(request, response);
}
else {
push(request, response);
}
the method that sends to the other servlet:
private void push(HttpServletRequest request, HttpServletResponse response) {
String url = "/PushServer";
try {
request.getServletContext().getRequestDispatcher(url).forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
and the servlet that processes the request:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if(FileFactory.getFileOperationsObject() == null || request.getParameterValues("input") == null) {
initiliaze(request, response);
String url = "/Display.jsp";
request.setAttribute("xRefFile", FileFactory.getXRefFileObjects());
request.setAttribute("platforms",FileFactory.getUniqueSortedPlatforms());
request.setAttribute("showModal", 0);
if(request.getParameter("results") == null) {
request.setAttribute("results", "Update Pending");
}
request.getServletContext().getRequestDispatcher(url).forward(request, response);
}
My only guess is that a new request is somehow being generated. If that is indeed what is happening - how do I avoid it?
The problem is method selection.
request.getParameter("yourAttributeName") only works for retrieving form data (<form></form>) - aka data from your .jsp page - as well as query parameters.
If one wishes to send information from one Java servlet to another Java servlet, as in the above code, one must use:
request.getAttribute("myAttributeName");

REST with Java using Jersey

I am making a restful call to the servlet doGet() method. Inside the doGet() method I am making a method call which takes a lot of time for processing due to which the doGet() method times out and cannot send a response back to the application which made the call.
So now I want to send a response back to the application which called the doGet() method immediately the doGet() is invoked.
Can I use Threads like one thread will reply back and the other one will continue with the method invocation. Do i need to use any webservice frame work like Jersey ?
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("in the Do Get");
String tableName = (String)request.getParameter("tableName");
tableName = tableName.replaceAll("[^A-Z0-9_]", "");
System.out.println("setup connections");
SampleService sampleService = new SampleService(new Properties());
Thread t = new Thread(new Runnable() {
public void run() {
// stuff here
sampleService.execute(tableName);
}
});
t.start();
i am making the class to implement the Runnable interface and writing the logic of the method call(the method which takes lot of time to process) inside the run method. Also how to send a response while this one is running
You can use 2 threads so one will respond and terminated and other will do the background job. This approach can be implemented in above code or you can user framework like Jersey. The major benefit of using any frameworks is frameworks hide complexities and provide easy to use and customizable interface (the concept of abstractions)
With Jersey, you can create Asynchronous API using AsyncResponse or you can use #ManagedAsync annotation along with AsyncResponse
One example is below -
#GET
#ManagedAsync
public void getMessage(#Suspended final AsyncResponse asyncResponse) {
System.out.println("1. Registering callback");
asyncResponse.register(new CompletionCallback() {
#Override
public void onComplete(Throwable throwable) {
if (throwable == null) {
// no error
System.out.println(
"4. Request processing is successful");
} else {
System.out.println(
"4. Error occurred in request processing");
}
}
});
System.out.println("2. Executing expensive operation");
String result = expensiveOperation();
System.out.println("3. Notify callback and send response ");
asyncResponse.resume(result);
System.out.println("5. Thread exiting");
}
Sysout statements are just for reference and can be removed.
If you want to do it with Servlet directly, then create one thread, start it and return your current response -
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("in the Do Get");
String tableName = (String)request.getParameter("tableName");
tableName = tableName.replaceAll("[^A-Z0-9_]", "");
System.out.println("setup connections");
SampleService sampleService = new SampleService(new Properties());
// this tread will run in even after response is send
Thread t = new Thread(new Runnable() {
public void run() {
// stuff here
sampleService.execute(tableName);
}
});
t.start();
// send the response
response.setContentType("application/json");
resp.getWriter().write("response JSON here");
return;
}
You can also use Jackson for object mapping to JSON for returning in response.

How can I recover the value after recovering control in a servlet?

I am trying to include several servlets in the main servlet to get finish some processs and retrieve values. In this example, I am receiving the control from a jsp file to the main servlet. After this servlet send call to the next servlet to carry out an operation related to a Java List and after returns the control to the main servlet. However, I am not able to recover the value of this List. How can I recover values from servlets that I am calling from the main servlet? The part of source code is the next:
(Main Servlet)
DeletePolicy.java:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setContentType("text/html");
PrintWriter printWriter = response.getWriter();
Client client= Client.create();
WebResource webResource= client.resource("http://localhost:8080/clientLibrary/webapi/policy");
//create an object of RequestDispatcher
RequestDispatcher rd = request.getRequestDispatcher("GetPolicy");
// send the client data available with req of delete to req of getPolicy with include()
rd.include(request, response);
// To receive the parameter from the second servlet
List<Policy> policies = (List<Policy>) request.getAttribute("policies");
printWriter.print("List of books in Delete: ");
for(Policy policy : policies) {
printWriter.println("<li>"+"ID: "+policy.getId()+"<br>"+"Max Number of Books: "+policy.getMax_books()+"<br>"+"Year of Book: "+policy.getYear_book()+"<br>"+"Activated: "+policy.getActivate()+"<br></li><br>");
}
printWriter.print("I am comming back in Delete to send a request to Delete method");
/*ClientResponse rs=webResource.accept(
MediaType.APPLICATION_JSON_TYPE,
MediaType.APPLICATION_XML_TYPE).
delete(ClientResponse.class,input);
printWriter.print("Delete a policy");*/
}
/* Include solution provided by Jozef Chocholacek: request.setAttribute("policies", policies);
GetPolicy.java(Second Servlet):
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter printWriter = response.getWriter();
Client client= Client.create();
WebResource webResource= client.resource("http://localhost:8080/clientLibrary/webapi/policy");
printWriter.println("<u>Searching for current policies...</u><br>");
ClientResponse rs=webResource.accept(
MediaType.APPLICATION_JSON_TYPE,
MediaType.APPLICATION_XML_TYPE).
get(ClientResponse.class);
//ClientResponse rs = webResource.type(MediaType.APPLICATION_JSON).delete(ClientResponse.class,input);
/*Transform json to java object*/
String jsonPolicy=rs.getEntity(String.class);
Gson gson = new Gson();
Policy[] PolicyA = gson.fromJson(jsonPolicy, Policy[].class);
List<Policy> policies = Arrays.asList(PolicyA);
for(Policy policy : policies) {
System.out.println(policy.getId()+" "+policy.getMax_books()+", "+policy.getYear_book()+", "+policy.getActivate()+", ");
}
//Send List to the servlet that is calling
request.setAttribute("policies", policies);
/*Display book list in the servlet*/
printWriter.println("<h1>List of Policies</h1>");
if (policies.isEmpty()){
printWriter.println("<html><body>Sorry, we did not have any policy"+"<br>");
}else{
printWriter.println("<html><body>The complete list of policies: <br>");
printWriter.println("<ul>");
for(Policy policy : policies) {
printWriter.println("<li>"+"ID: "+policy.getId()+"<br>"+"Max Number of Books: "+policy.getMax_books()+"<br>"+"Year of Book: "+policy.getYear_book()+"<br>"+"Activated: "+policy.getActivate()+"<br></li><br>");
}
}
printWriter.println("</body></html>");
}
Thank you in advance
Cheers
Well, in your first servlet (DeletePolicy.java) you use
List<Policy> policies = (List<Policy>) request.getAttribute("policies");
but the second servlet (GetPolicies.java) does not store this list into request. You have to add
request.setAttribute("policies", policies);
into your second servlet.

Jsp that calls a web service in domain

I want to write a .jsp (tomcat5.5) that calls a web service (IIS in domain). I get an HTTP Error 401 Unauthorized. It seems that in order to call the web service you have to be a domain user. I want to allow access to the jsp only to domain users. The request.getRemoteUser() in the jsp returns null but not the domain user that calls the jsp.
From a web browser I call the web service and it works fine.
I am a bit confused with this. Can someone tell me how can the issue be resolved?
Do i have to make tomcat make SSO?
Thank you for your time.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter o = response.getWriter();
o.println("sstarting...");
o.println("user.name ".concat(System.getProperty("user.name")));
o.println("request.getRemoteUser() ".concat(request.getRemoteUser()));
try {
GetUserRoles getUserRolesRequest = new GetUserRoles();
getUserRolesRequest.setApplicationId(121);
getUserRolesRequest.setUserName("user");
GetUserRolesResponse getUserRolesResponse;
ServiceStub stub =new ServiceStub() ;
stub._getServiceClient().getOptions().setProperty(HTTPConstants.CHUNKED,"false");
getUserRolesResponse = stub.getUserRoles(getUserRolesRequest); //IT FAILS HERE 401
String str =getUserRolesResponse.getGetUserRolesResult().toString();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
o.println(e.getMessage());
}
}

how to clear contents of a PrintWriter after writing

Good evening, i want to know how to clear the data written to a PrintWriter, i.e. is it possible to remove the data from a PrintWriter after printing?
here in this servlet i print some text to the response and at the line denoted by # i want to remove all the previously printed data and print new stuff:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
String uName = request.getParameter("uName");
String uPassword = request.getParameter("uPassword");
if (uName .equals("Islam")) {
out.println("Valid-Name");
if (uPassword !=null) {
if (uPassword .equals("Islam")) {
// # clear the writer from any printed data here
out.println("Valid-password");
} else {
out.println("");
out.println("InValid-password");
}
}
} else {
out.println("InValid-Name");
}
}
Note: i tried out.flush() but the old printed text remains
Create an in-memory PrintWriter using a StringWriter. You can get the underlying buffer from the StringWriter and clear it if you need to.
StringWriter sr = new StringWriter();
PrintWriter w = new PrintWriter(sr);
w.print("Some stuff");
// Flush writer to ensure that it's not buffering anything
w.flush();
// clear stringwriter
sr.getBuffer().setLength(0);
w.print("New stuff");
// write to Servlet out
w.flush();
response.getWriter().print(sr.toString());
HttpServlteResponse.resetBuffer() will clear the buffered content. But yes, if the response is already flushed to the client it will throw IllegalStateException. Because it is illegal to clear after partial response is sent to the client.
resetBuffer........
void resetBuffer()
Clears the content of the underlying buffer in the response without clearing headers or status code. If the response has been committed, this method throws an IllegalStateException.
References:
Cause of Servlet's 'Response Already Committed'
You can't do that with the original PrintWriter you get from the response, as that's backed by the actual OutputStream corresponding to the client connection. What you write there goes right to the browser via the wire (after some buffering), so you can't "take it back".
What you can do is write your message in some StringBuilder and once you know it's good to go, write it to the PrintWriter.
If you want this logic to be applied in multiple places (transparently), you can consider writing a filter that wraps the original response in an HttpServletResponseWrapper which returns a "fake" OutputStream or PrintWriter and performs this check prior to actually sending it over the wire.
public class CensorshipFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
CensorshipResponseWrapper wrapper = new CensorshipResponseWrapper(httpServletResponse);
chain.doFilter(request, wrapper);
String output = wrapper.sw.toString();
if ( output.contains("Some forbidden pattern") ) { // your check goes here
// throw exception or whatever
} else { // write the whole thing
httpServletResponse.getWriter().write(output);
}
}
#Override
public void destroy() {
}
static class CensorshipResponseWrapper extends HttpServletResponseWrapper {
private final StringWriter sw = new StringWriter();
public CensorshipResponseWrapper(HttpServletResponse response) {
super(response);
}
#Override
public ServletOutputStream getOutputStream() throws IOException {
// you may also fake the output stream, if some of your servlets use this method
return super.getOutputStream();
}
#Override
public PrintWriter getWriter() throws IOException {
return new PrintWriter(sw);
}
}
}
What ended up working for me was to change the logic of how I was outputting my data.
This is the data structure I was outputting that stored the results of a search using the text from a html form as input.
private final TreeMap<String, ArrayList<SearchResult>> searchResults;
So I was iterating over the contents of this data structure and printing it out to html.
public void writeSearchResultsToHtml(PrintWriter writer)
{
try
{
JSONTreeWriter. writeSearchResultsToHtml(searchResults, writer);
} catch (ArithmeticException | IllegalArgumentException | IOException | NoSuchElementException e)
{
System.err.println("Unable to write the search results builder to JSON to the file html.");
}
// clear results for next search otherwise
// the next search will contain the previous
// results, store them in history.
searchResults.clear();
}
Clearing the data structure worked great given my servlet setup.
Here was my main serverlet loop logic:
public void startServer()
{
// seed the database for testing
crawler.startCrawl("http://cs.usfca.edu/~cs212/birds/birds.html");
index.toJSON("index.json");
// type of handler that supports sessions
ServletContextHandler servletContext = null;
// turn on sessions and set context
servletContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
servletContext.setContextPath("/");
servletContext.addServlet(ViewServlet.class, "/");
// default handler for favicon.ico requests
DefaultHandler defaultHandler = new DefaultHandler();
defaultHandler.setServeIcon(true);
ContextHandler defaultContext = new ContextHandler("/favicon.ico");
defaultContext.setHandler(defaultHandler);
// setup handler order
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{defaultContext, servletContext});
openWebBrowser();
// setup jetty server
Server server = new Server(portNumber);
server.setHandler(handlers);
try
{
server.start();
server.join();
} catch (Exception e)
{
e.printStackTrace();
}
}

Categories

Resources