I'm getting the following exception while calling a servlet:
com.ibm.ws.webcontainer.async.AsyncIllegalStateException: SRVE8010E: The current request does not support asynchronous servlet processing.
The servlet looks like this:
public class AsyncServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
AsyncContext async = req.startAsync();
async.start(new Runnable(){
#Override
public void run() {
System.out.println("Bazinga");
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
I've tried to set it as asynchronous using annotations:
#WebServlet(urlPatterns = "/asyncServlet", asyncSupported = true)
And also in web.xml after reading a post in a forum:
<servlet>
<display-name>AsyncServlet</display-name>
<servlet-name>AsyncServlet</servlet-name>
<servlet-class>com.lala.lala.AsyncServlet</servlet-class>
<init-param>
<param-name>com.ibm.ws.webcontainer.async-supported</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>AsyncServlet</servlet-name>
<url-pattern>/asyncServlet</url-pattern>
</servlet-mapping>
Still getting the AsyncIllegalStateException. How did you get async servlets run on WAS8?
I found something similar on one of the forums, maybe it will help:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet(urlPatterns = "/AsyncServlet", asyncSupported = true)
public class AsyncServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Record the servlet's thread
PrintWriter out = response.getWriter();
out.printf("<h3>Servlet's thread: %s</h3>", Thread.currentThread());
out.flush();
// Put the request into asynchronous mode
request.startAsync();
// Run an asynchronous task via servlet 3.0's abstractions
AsyncContext asyncCtx = request.getAsyncContext();
MyTask mt = new MyTask(asyncCtx);
asyncCtx.start(mt);
// Run another asynchronous task via java's abstractions
MyTask mt02 = new MyTask(asyncCtx);
new Thread(mt02).start();
out.printf("<h3>Servlet finishes its job</h3>");
}
public class MyTask implements Runnable {
AsyncContext asyncContext;
public MyTask(AsyncContext asyncContext) {
this.asyncContext = asyncContext;
}
#Override
public void run() {
ServletResponse response = asyncContext.getResponse();
try {
// do the time-consuming job
PrintWriter out = response.getWriter();
for (int i = 0; i < 5; i++) {
out.printf("<h2>Hello from thread: %s (%d)</h2>", Thread.currentThread(), i);
out.flush();
Thread.sleep(1 /* secs */ * 1000);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
asyncContext.complete();
}
}
}
}
found here
Related
I am using the jdbc bolt library for connecting to a Neo4J database in Java. My code runs perfectly in main method, but after I switch it to servlet it gives error No suitable driver found for 'jdbc:neo4j:bolt://localhost'. What should I do?
//Test class
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class Test {
public void test() {
try {
Connection con = DriverManager.getConnection("jdbc:neo4j:bolt://localhost", "neo4j", "neo4j");
String query = "MATCH (n) return id(n)";
PreparedStatement ps = con.prepareStatement(query);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
System.out.println("RESULT: " + rs.getObject("id(n)"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//Servlet
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet("/testingservlet")
public class testingservlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public testingservlet() {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
new Test().test();
} catch (Exception e) {
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
Use official java library for neo4j database connectivity.
I need to load some servlet from jar file and map it to the URL in Tomcat.
Servlet code is
package net.arturik.mymodulepackage;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet(name = "QWERTY", urlPatterns = {"/qqq"})
public class QWERTY extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
/* TODO output your page here. You may use following sample code. */
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet QWERTY</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet QWERTY at " + request.getContextPath() + "</h1>");
out.println("</body>");
out.println("</html>");
}
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
#Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
Servlet compiled and stored in file MyModulePackage-1.0-SNAPSHOT.jar.
In Java Web App I has ServletContextListenerImpl class:
package net.arturik.testosgispring;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebListener;
#WebListener
public class ServletContextListenerImpl implements ServletContextListener {
#Override
public void contextInitialized(final ServletContextEvent sce) {
try {
System.out.println("++++++++++++++");
final ServletContext servletContext = sce.getServletContext();
//////////////////////////////////////////////
String pathToJar = "m:\\myhostingpanel\\myhostingpanel\\Tests\\MyModulePackage\\target\\MyModulePackage-1.0-SNAPSHOT.jar";
JarFile jarFile = new JarFile(pathToJar);
Enumeration e = jarFile.entries();
URL[] urls = {new URL("jar:file:" + pathToJar + "!/")};
URLClassLoader cl = URLClassLoader.newInstance(urls, this.getClass().getClassLoader());
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
if (je.isDirectory() || !je.getName().endsWith(".class")) {
continue;
}
// -6 because of .class
String className = je.getName().substring(0, je.getName().length() - 6);
className = className.replace('/', '.');
Class c;
Object obj;
try {
System.out.println("className !!! " + className);
c = cl.loadClass(className);
obj = c.newInstance();
System.out.println(c.getPackage() + " " + c.getName());
Class noparams[] = {};
// Method method = c.getDeclaredMethod("qqq", noparams);
// method.invoke(obj, null);
// MyInter obj1 = (MyInter) c.newInstance();
// obj1.qqq();
System.out.println("registering");
final ServletRegistration.Dynamic dynamic = servletContext.addServlet("QWERTY", c);
dynamic.addMapping("/qqq");
final Map<String, ? extends ServletRegistration> map = servletContext.getServletRegistrations();
for (String key : map.keySet()) {
System.out.println("Registered Servlet: " + map.get(key).getName());
}
System.out.println("end of registering ");
} catch (Exception ex) {
ex.printStackTrace();
}
}
//////////////////////////////////////////////
} catch (IOException ex) {
Logger.getLogger(ServletContextListenerImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void contextDestroyed(final ServletContextEvent sce) {
//NO-OP
}
}
This code got output
++++++++++++++
className !!! net.arturik.mymodulepackage.QWERTY
package net.arturik.mymodulepackage net.arturik.mymodulepackage.QWERTY
registering
Registered Servlet: default
Registered Servlet: jsp
Registered Servlet: QWERTY
Registered Servlet: T1
Registered Servlet: mvc-dispatcher
Registered Servlet: T2
Registered Servlet: T3
end of registering
As we can see - servlet registered successfully.
But if I try to open page /qqq , Tomcat got Exception
22-Nov-2014 02:07:56.846 SEVERE [http-nio-8082-exec-5] org.apache.catalina.core.StandardWrapperValve.invoke Allocate exception for servlet QWERTY
java.lang.ClassNotFoundException: net.arturik.mymodulepackage.QWERTY
As I understand - it is a class visibility problem - my class initialized by URLClassLoader and my class doesn't passed to the main (system) Class Loader.
How can I pass my class, loaded by URLClassLoader to the system class loader for global visibility?
Recently i have started working on Java Servlet Async functionality. I have written sample code shown below to check aysnc Functionality. I am running it on single core processor. I am submitting 100 requests (image requests) from jsp. I have added "Request Submmited:::" SOP in code. It is displaying SOP for first 0 to 6 requests then after some time it is displaying SOP for 6 to 11.... why it is not displaying SOP for all 100 requests.
package com.test;
import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet(urlPatterns={"/Test"}, asyncSupported = true)
public class Test extends HttpServlet {
private static final long serialVersionUID = 1L;
public Test() {
super();
}
int counter = 0;
#Override
protected void doGet(final HttpServletRequest request,
final HttpServletResponse response) throws ServletException,
IOException {
System.out.println("Request Submmited:::" + counter++);
final AsyncContext ctx = request.startAsync();
ctx.start(new Runnable() {
public void run() {
try {
String count = request.getParameter("test");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FileInputStream fin = new FileInputStream(
"D:/TESTImages/8_0_0_NUCLEI" + count + ".jpg");
byte[] data = new byte[fin.available()];
fin.read(data);
response.getWriter().print(new String(data));
response.flushBuffer();
} catch (Exception e) {
e.printStackTrace();
}
ctx.complete();
}
});
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
Seems that the default thread pool size is 5, for the pool that procesess async requests in your servlet container. Try providing init params as below:
#javax.servlet.annotation.WebServlet(urlPatterns={"/Test"}, asyncSupported = true,
initParams = { #WebInitParam(name = "threadpoolsize", value = "100") })
So my Problem is that I have to create a Singleton pattern counter for numeric name giving. For example "1", "2", "3" etc. The idea is that every time i start the application and the Server(tomcat), it gets the last number and when I upload another image it should continue from there. Lets say the last one was "43", so the the next time I start the application it should know it and put "44" for the next image upload.
I'm not that good in Java so please give me some patience :)
This is my FileUploadServlet. It handles the request from the fileUploadForm.jsp by taking the file from the submit.
package upload;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import utils.FormatChecker;
import utils.UnzipFile;
//Servlet for handling the Upload request from the Index.jsp
#MultipartConfig
public class FileUploadServlet extends HttpServlet {
// Instace of the FileUpload object
private FileUploader uploader = new FileUploader();
// Instance of the FormatChecker object
private FormatChecker checker = new FormatChecker();
// Instance of the UnzipFile object
private UnzipFile unzip = new UnzipFile();
private static final long serialVersionUID = 1L;
private static final String SAVE_FOLDER = "C:\\Users\\cuche\\Desktop\\tomcat\\apache-tomcat-7.0.47\\webapps\\files";
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect("error.jsp");
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String contentType;
boolean isFormatValid;
Part filePart = request.getPart("file");
contentType = filePart.getContentType();
ServletContext context = getServletContext();
String appPath = context.getRealPath("/");
String fileNameOld = getFileName(filePart);
String fileNameNew = appPath + fileNameOld;
isFormatValid = checker.check(contentType);
pleas ignore the part with the FileUnziper
if (isFormatValid == true) {
if (contentType == ("application/x-zip-compressed")) {
unzip.FileUnziper(fileNameNew, SAVE_FOLDER);
} else {
//gets the content and saves in form of a stream
InputStream fileContent = filePart.getInputStream();
//using the uploadImage method of uploader class
uploader.uploadImage(fileNameNew, fileContent);
}
try {
response.sendRedirect("result.jsp");
} catch (IOException ex) {
response.getWriter().append(ex.getLocalizedMessage());
}
} else {
response.getWriter().append("Format is wrong");
}
}
// method for removing header for proper file upload
private String getFileName(Part part) {
for (String cd : part.getHeader("content-disposition").split(";")) {
if (cd.trim().startsWith("filename")) {
String filename = cd.substring(cd.indexOf('=') + 1).trim()
.replace("\"", "");
return filename.substring(filename.lastIndexOf('/') + 1)
.substring(filename.lastIndexOf('\\') + 1); // MSIE fix.
}
}
return null;
}
}
This is my FileUploader class
package upload;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* #author Iwan Cuche
* #date:
*/
public class FileUploader {
/**
* This method reads a File
*
* #param fileName
* #param stream
*/
public void uploadImage(String fileName, InputStream stream)
throws IOException {
try {
File file = new File(fileName);
OutputStream os = new FileOutputStream(file);
int data;
while ((data = stream.read()) != -1) {
os.write(data);
}
os.flush();
os.close();
System.out.println("Uploaded file successfully saved in "
+ file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
throw e;
}
}
}
This is my Singleton class
package utils;
public class ServerCounter {
private static ServerCounter INSTANCE = new ServerCounter();
private ServerCounter() {};
public static ServerCounter getInstance() {
return INSTANCE;
}
}
I hope someone can help me because I'm not sure how to go at it.
In ServerCounter, add
private final AtomicLong counter = new AtomicLong();
public String nextval() { return String.valueOf(counter.incrementAndGet()); }
Each time you call INSTANCE.nextval() you'll get a fresh numeric string.
Clearly, each time you restart your application, the counter will restart.
ok, first you have to persist your counter if you want to get it after tomcat shutdown. we need listener for tomcat:
package utils;
public class ContextListener implements ServletContextListener{
void contextInitialized(ServletContextEvent sce){ // we could call loadFromFile here as well
}
//will be executed at tomcat shutdown
void contextDestroyed(ServletContextEvent sce){
ServerCounter .getInstance().writeToFile();
}
}
now the singleton(like in Marko's answer:)):
package utils;
public class ServerCounter {
private static ServerCounter INSTANCE = new ServerCounter();
private final AtomicLong counter;
private ServerCounter() {
//load value from file, do you need help by it?
long value = this.loadCounterFromFile();
counter = new AtomicLong(value);
};
private long loadCounterFromFile(){
BufferedReader br = null;
try {
//no problem if there is no file, we will return 0 in this case
br = new BufferedReader(new FileReader("C:\\Test\\counter.txt"));
String line = br.readLine();
if(line != null && line.length() > 0)
return Long.parseLong(line);
return 0;
//catch all exceptionse, because we could get NumberFormatException or FileNotFound from parseLong
} catch (Exception e) {
return 0;
} finally {
try {
if (br != null)br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public static ServerCounter getInstance() {
return INSTANCE;
}
public String nextval() { return String.valueOf(counter.incrementAndGet()); }
//will be executed by listener
public void writeToFile(){
//write the counter to file
writeToFile(counter.get());
}
private void writeToFile(long value){
try{
//you need folder c:\Test, file will be created automatically if there is no file, it will override the old file
BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Test\\counter.txt"));
//need "" to create String
bw.write("" + value);
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
now you can use ServerCounter.getInstance.nextval() to increment the counter and get the value
last thing is, you need to put the listener to your webApplication:
<web-app>
...
<listener>
<listener-class>utils.ContextListener </listener-class>
</listener>
</web-app>
EDIT: ServerCounter was implementing ServletContextListener by mistake
EDIT2: added read/write file
I have a Jersey Web-Service that I need to parse some json data that was send along with a request.
#POST
#Path ("/authenticate")
#Produces (MediaType.APPLICATION_JSON)
public Response authenticate (#Context HttpServletRequest request)
{
try {
StringBuffer json = new StringBuffer ();
BufferedReader reader = request.getReader();
int line;
while ((line = reader.readLine()) != null)
{
json.append(line);
}
System.out.prinln (json);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return Response.ok().entity(json).build();
}//end authenticate method
This service generates the following Exception:
java.lang.IllegalStateException: getInputStream() has already been called for this request
I did some research that suggests a getReader and getInputStream cannot be called on the same request. Therefore, it seemed like a getInputStream instance is already called. How is this possible if I haven't made a explicit call to it? To solve this problem, I used the getInputStream method instead
try {
ServletInputStream reader = request.getInputStream();
int line;
while ((line = reader.read()) != -1)
{
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return Response.ok().entity().build();
With this approach, how can I use the int of bytes to get the json?
Seems like you're missing a #Consumes annotation. You realise you can just have a method;
#POST
#Path ("/authenticate")
#Consumes (MediaType.APPLICATION_JSON)
#Produces (MediaType.APPLICATION_JSON)
public Response authenticate (String entity) {
//entity contains the posted content
}
Without having to read the stream yourself? If you have a bean representing your consumed JSON , then you can just add it as a method param and jersey will automatically parse it for you;
#POST
#Path ("/authenticate")
#Consumes (MediaType.APPLICATION_JSON)
#Produces (MediaType.APPLICATION_JSON)
public Response authenticate (AuthBean auth) {
//auth bean contains the parsed JSON
}
class AuthBean {
private String username;
private String password;
// getters/setters
}
Example post;
{
"username" : "joe#example.com",
"password" : "super s3cret"
}
we can read from the HttpServletRequest only once, so we have to be using HttpServletRequestWrapper inside a filter before reading the request and use the wrapper for subsequent calls for multiple times..
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import com.dbs.bds.ingestion.util.MultiReadRequestWrapper;
import lombok.extern.slf4j.Slf4j;
#Slf4j
public class SessionValidationFilter implements Filter {
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
try {
log.debug("inside filter");
HttpServletRequest httpServletRequest = new MultiReadRequestWrapper((HttpServletRequest) servletRequest);
filterChain.doFilter(httpServletRequest, servletResponse);
} catch (Exception ex) {
log.error("error inside filter:{}", ex.getMessage());
}
}
}
The below is the code for Wrapper which we used in above Filter.
import org.apache.commons.io.input.BoundedInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
public class MultiReadRequestWrapper extends HttpServletRequestWrapper {
private static final Logger LOG = LoggerFactory.getLogger(MultiReadRequestWrapper.class);
// We include a max byte size to protect against malicious requests,
//since this all has to be read into memory
public static final Integer MAX_BYTE_SIZE = 1_048_576; // 1 MB
private StringBuilder body;
public MultiReadRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = new StringBuilder("");
try (
InputStream bounded = new BoundedInputStream(request.getInputStream(), MAX_BYTE_SIZE);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(bounded));){
String line;
while ((line = bufferedReader.readLine()) != null) {
body.append(line);
}
} catch(Exception e) {
LOG.error(e.getMessage());
}
}
#Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.toString().getBytes());
return new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
#Override
public boolean isFinished() {
return byteArrayInputStream.available() == 0;
}
#Override
public boolean isReady() {
return true;
}
#Override
public void setReadListener(ReadListener readListener) {
//do nothing
}
};
}
#Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
Now expose the above filter as bean
#Bean(name = "sessionValidationFilter")
public Filter getSessionValidationFilter() {
return new SessionValidationFilter();
}
#SuppressWarnings({"rawtypes", "unchecked"})
#Bean
public FilterRegistrationBean sessionValidationFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(getSessionValidationFilter());
registration.addUrlPatterns("/v1/create/record");
registration.setName("sessionValidationFilter");
return registration;
}