show servlet's response.getWriter().println() before servlet's ends - ajax

first of all I want to say that I am new in html/jsp/java/servlets, etc... and thanks to this forum i managed to get my first webapp working. But now I am having a problem and i couldnt find a solution on the site.
The problem is that I call a servlet from a jsp, this servlet deploys different applications and I simply want to show the println that I call in the servlet before de servlet ends, right now, even If I have 10 println in different moments of the deploy process, the server only shows them when the servlets ends processing, which doesnt hace much sense for my app because i am trying to show the different steps of the deploy.
The servlet code is something like this:
public class Deploys extends HttpServlet {
String HOME = System.getenv("TRACE_HOME");
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
final PrintWriter out = res.getWriter();
String broker = req.getParameter("Broker");
String eg = req.getParameter("Eg");
String servicio = req.getParameter("cboServicios");
String bar = req.getParameter("cboBarFiles");
// deploy
BrokerProxy b;
try {
out.println("connecting to server");
b = utils.connect("LOCALQM");
out.println("connect succesfull");
ExecutionGroupProxy e = b.getExecutionGroupByName(eg);
String path = HOME + "\\deploys\\files\\" + servicio + "\\";
DeployResult dr = e.deploy(path + bar,true, 60000);
out.println("Deployment completion code = "+dr.getCompletionCode());
} catch (ConfigManagerProxyLoggedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ConfigManagerProxyPropertyNotInitializedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
and the server shows this all at the same time
connecting to server
connect succesfull
starting deploy
deploy completed
I read that the way to to this is using ajax an jquetr but I couldnt find an example of how to do it, so if any one can help will be very appreciated

It's because it only does everything when the servlet is fully deployed, so it will do everything on the servlet almost instantly. At least that's how I learned it.
I think you could only do it editing the server or something like that. I don't think it's possible to do it on jQuery or ajax because the servlet would already be deployed. What you can do, however, is to do those outputs at servlet execution, so it prints while it's processing the code.

OK, I found a solution, I am not sure if its the best way to do it or if it is just a workaround, but it works!
I used flush() and the most important is that I had to set the response type in the servlet.
This is how my "hello world" servlet used to test this case finally works.
public class HolaMundo extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/css");
PrintWriter out = response.getWriter();
out.println("Hello World! entrada");
out.flush();
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
out.println("Hello World! salida");
out.flush();
}
}

Related

How to enable Spring Boot to display a list of files under a directory

I have a folder structure /data/reports on a file system, which contains all reports.
How can I configure a SpringBoot application to serve the contents of this file sytem.
Currently I have tried few options, but none working
#Configuration
#EnableWebMvc
public class AppConfig implements WebMvcConfigurer {
#Value(value = "${spring.resources.static-locations:#{null}}")
private String fileSystem;
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/data/reports/**")
.addResourceLocations(fileSystem)
.setCachePeriod(3600)
.resourceChain(true)
.addResolver(new PathResourceResolver());
}
}
and in application.properties I have defined
spring.resources.static-locations=file:///data/reports
server.servlet.jsp.init-parameters.listings=true
But in both cases, when I try
http://host:port/application/data/reports
I'm getting 404
What am I missing ?
Based on the suggestions given, I realized that one mistake I'm doing is to access the reports via
http://host:port/application/data/reports
instead of
http://host:port/data/reports
if I use application in the request, those calls will go through RequestDispatcher and will try to find for a matching RequestMapping, which does not exist. I think I'm convinced so far.
But the problem I'm seeing now is, I'm getting SocketTimeoutException while trying to read from the resource listed in the URL. I had put some breakpoints in Spring source "ResourceHttpMessageConverter.java"
protected void writeContent(Resource resource, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
try {
InputStream in = resource.getInputStream(); //It is timing out here
try {
StreamUtils.copy(in, outputMessage.getBody());
}
catch (NullPointerException ex) {
// ignore, see SPR-13620
}
The resource is a small text file with 1 line "Hello World". Yet it is timing out.
The resource in the above class is a FileUrlResource opened on file:///c:/data/reports/sample.txt
On the other hand, I tried to read that resource as
File file = new File("c:/data/reports/sample.txt");
System.out.println(file.exists());
URL url = file.toURI().toURL();
URLConnection con = url.openConnection();
InputStream is = con.getInputStream(); //This works
Thanks

Olingo with Spring Boot

I am using this tutorial and it works for a simple java web application. Now I want to convert it to Spring Boot. I remove the web.xml and add the following two annotations to DemoServlet
#RestController
public class DemoServlet extends DispatcherServlet {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(DemoServlet.class);
#RequestMapping("/DemoService.svc/*")
protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
try {
// create odata handler and configure it with CsdlEdmProvider and Processor
OData odata = OData.newInstance();
ServiceMetadata edm = odata.createServiceMetadata(new DemoEdmProvider(), new ArrayList<EdmxReference>());
ODataHttpHandler handler = odata.createHandler(edm);
handler.register(new DemoEntityCollectionProcessor());
// let the handler do the work
handler.process(req, resp);
} catch (RuntimeException e) {
LOG.error("Server Error occurred in ExampleServlet", e);
throw new ServletException(e);
}
}
}
I also change the HTTPServlet to DispatcherServlet.
Now I am only able to access one end point. i.e.
http://localhost:8080/DemoService.svc/
The metadata end point is not working. It returns the service document instead of xml content.
http://localhost:8080/DemoService.svc/$metadata
Can somebody explain what is going on here?
user the below code for the process method.
handler.process(new HttpServletRequestWrapper(request) {
// Spring MVC matches the whole path as the servlet path
// Olingo wants just the prefix, ie upto /odata, so that it
// can parse the rest of it as an OData path. So we need to override
// getServletPath()
#Override
public String getServletPath() {
return "/DemoService.svc";
}
}, response);
You can create a #Configuration and Map your servlet in it like the following
#Bean
public ServletRegistrationBean odataServlet() {
ServletRegistrationBean odataServRegstration = new ServletRegistrationBean(new CXFNonSpringJaxrsServlet(),
"/DemoService.svc/*");
Map<String, String> initParameters = new HashMap<>();
initParameters.put("javax.ws.rs.Application", "org.apache.olingo.odata2.core.rest.app.ODataApplication");
initParameters.put("org.apache.olingo.odata2.service.factory",
"com.metalop.code.samples.olingo.springbootolingo2sampleproject.utils.JPAServiceFactory");
odataServRegstration.setInitParameters(initParameters);
return odataServRegstration;
}
Add the following after the handler.register call:
req.setAttribute("requestMapping", "/DemoService.svc");
The best implementation of olingo2 and spring-boot can be found here. I would suggest to take a look at this repository, it is very straight forward and easy.

ExecutorService for Runtime.exec in Spring Boot the right way

I want to use Java ExecutorService in a Spring Boot application.
Multiple module of the application is called as #Scheduled.
This module calls a Process to get a result from an external application using Runtime.exec. The process is supposed to get a result which is processed by java
This method can be called as part of a Scheduled thread as well as part of a request and response which can be called 24/7 . Multiple instances of the method can be running at a time.
Is it optimum to use ExecutorService defined as a local variable like this or some other method is recommended.
The requirement is that Java should not be infinitely waiting to get a result. It should be timed out.
Here is the method called
public String getExternalInformation(String applicationPath, String command, int noOfTries)
{
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future;
boolean taskExecuted=false;
int trialNumber=0;
String response = "";
while((!taskExecuted)&&(trialNumber<noOfTries))
{
trialNumber++;
log.info("Starting Trial: "+trialNumber);
future= executor.submit(new TestProcessTask(applicationPath,command));
try {
System.out.println("Started Information Fetching ");
response=future.get(3, TimeUnit.MINUTES);
taskExecuted =true;
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("Timed out!");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdownNow();
return response;
}
The call() method of the TestProcessTask will call the Runtime.exec and parse the returning OutputStream.
I implemented Async in Spring as suggested by M. Deinum
Using the same Future methods and got it working.,

GWT FormPanel onSubmitComplete event not firing when downloading a file

I created servlet to download file from a server. In GWT I created a FormPanel and I am able to download a file.
Problem is, that I want to fire an event, when the file is ready. I tried to use onSubmitComplete event, but it isn't firing.
I found a suggestion, to change ContetType to "text/html", but still no luck. I found, that the problem lies in writing to OutputStream - when commented out, event is fired.
Here is my servlet code
public void handleRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
response.setHeader("Content-Disposition", "attachment; filename=File.xls");
HSSFWorkbook workbook = new HSSFWorkbook();
try {
workbook = fileCreator.getWorkbook();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
OutputStream out = response.getOutputStream();
workbook.write(out);
out.close();
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().print("something");
response.flushBuffer();
}
So file is downloaded successfully, but event is not triggered. Even when I just get OutputStream and close it (without writing to it), event stops working.
When I remove whole "writing-to-output-stream" code, event works like a charm.
Any suggestions?
UPDATE
Here is code for FormPanel and its handlers, meby there is a problem?
Form:
downloadFileFormPanel.setEncoding(FormPanel.ENCODING_URLENCODED);
downloadFileFormPanel.setMethod(FormPanel.METHOD_POST);
VerticalPanel panel = new VerticalPanel();
panel.setWidth(UIConstatns.SIZE_100percent);
downloadFileFormPanel.setWidget(panel);
downloadFileButton = new Button(messages.EXPORT_LIMITS());
downloadFileButton.setWidth(UIConstatns.SIZE_100percent);
downloadFileButton.addStyleName("navigation-button");
panel.add(downloadFileButton);
Handlers
private void registerExportLimitsHandler() {
registerHandler(getView().getDownloadFileButton().addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
getView().showLoadingDialog();
getDownloadFileForm().submit();
}
}));
}
private void registerFormSubmitCompleteHandler() {
getView().getDownloadFileForm().addSubmitCompleteHandler(new SubmitCompleteHandler() {
public void onSubmitComplete(SubmitCompleteEvent event) {
Window.alert("download complete");
getView().hideLoadingDialog();
}
});
}
According to the Javadoc of ServletResponse#getWriter() you can either use response.getOutputStream() or response.getWriter() to write the body of the response, but not both. Furthermore it is better to set the status code of the response before writing the body. Please try the following:
// ...
response.setStatus(HttpServletResponse.SC_OK);
OutputStream out = response.getOutputStream();
workbook.write(out);
out.flush();
out.close();
// response.getWriter().print("something");
// response.flushBuffer();
You did not post the line where you create your FormPanel so I'm not sure if this was your problem:
Looks like the FormPanel(String target) constructor does not work with the SubmitCompleteHandler. With the default constructor it seems to work.

Spring 3 MVC, stream response asynchronously

I'd like to stream out my content using OutputStream or Writer from Spring MVC controller method using async solution, i.e. not to block base threadpool used for http requests. As far as I could find is to use DefferedResult<?> for async in general. It's fine when you return a view string name but can't think of a way it would work with stream. Could not find anything helpful.
Thanks
As described here you can perform computation in another thread thereby unloded http thread pool.
You can try to combine DefferedResult and byte[] (DefferedResult) return type(previously registering ByteArrayHttpMessageConverter). So the final method will look like this:
#ResponseBody
public DefferedResult<byte[]> foo(HttpServlet response) {
//set headers using response
response.setContentType("someContentType");
...
DefferedResult<byte[]> r = new DefferedResult<>();
executionService.submit(() -> {
r.setResult(getBytes());
});
return r;
}
Another option is to combine Defferedresult and ResponseEntity. Do not forget to use it in servlet 3.0+ container
It may be that what you are looking for is the following. Not sure if it blocks the http thread pool though.
#Controller
public class TestController {
#RequestMapping("/")
public StreamingResponseBody handleRequest () {
return new StreamingResponseBody() {
#Override
public void writeTo (OutputStream out) throws IOException {
for (int i = 0; i < 1000; i++) {
out.write((Integer.toString(i) + " - ")
.getBytes());
out.flush();
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
}
}

Resources