Lightweight servlet engine for serving java application via IIS - java

I have an old legacy java web application that I want to deploy on the same server as my asp.net-applications (running on IIS 7). And I need to have all applications running on port 80, so I can't just install two web servers on different ports.
The java-application is really simple, just a couple of serverlets (no JSP) with functionality pretty close to "Hello World". So I want the servlet engine to be as lightweight as possible. I consider Tomcat to be overkill for this.
Does such a product exist or I'm I stuck with Tomcat?

Have a look at Jetty. It can be invoked from a standard Main invocation, and handles servlet containers pretty well (GWT debugging is hosted in a Jetty environment, for example).
I've used this for debugging Lift applications, and been pretty impressed.
To forward requests through IIS to Jetty you can try mod_jk. The problem is that IIS and Java/JSP don't Just Work because IIS needs add-ons to support the loading of the VM and the reflection of JSP/Java content. There is an excellent article on how this can be done here.

I'm sure you don't want to get too exotic but if you don't find something to your liking, you could always run Tomcat on a different port and then do some reverse proxying and send everything heading to a specific context to your Tomcat install running on port XYZ, although admittedly I'm only familiar with this in the Apache world, and not the IIS world.

Check out JK, it has an Apache module and I think it also has an IIS module to connect with Tomcat (maybe Jetty, I don't know). This will allow you to run your app on Tomcat on some other port (even on some other host) and access it through your IIS.
http://tomcat.apache.org/connectors-doc/

If you use Java 6, there is a HTTP server built-in,
http://java.sun.com/javase/6/docs/jre/api/net/httpserver/spec/com/sun/net/httpserver/package-summary.html
Of course, this wouldn't be a good solution if you care about portability.

Use HTTP server that comes with java version 6 or more. Straight forward code.
As suggested above, REST can be implemented using Servlet technology.We cannot compare both.
Servelet is an adapter(Java) that converts http request to Java object/s and triggers a method(doGet/doPost) when ever the request Arrives and sends http response as per instructed in Java programatically.
public class server {
public static void main(String[] args) throws Exception {
//Start server
HttpServer server = HttpServer.create(new InetSocketAddress(8000, 0);
server.createContext("/monitor", new MyHandler());
server.createContext("/usage", new MyHandler());
server.setExecutor(java.util.concurrent.Executors.newCachedThreadPool()); //Uses New Thread every time
server.start();
System.out.println("Server Started at 8000...");
}
static class MyHandler implements HttpHandler {
#Override
public void handle(HttpExchange t) throws IOException {
URI uri = t.getRequestURI();
String path = uri.getPath();
InputStreamReader isr = new InputStreamReader(t.getRequestBody(), StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr);
int b;
StringBuilder buf = new StringBuilder(512);
while ((b = br.read()) != -1) {
buf.append((char) b);
}
br.close();
isr.close();
JSONObject body = null;
try {
body = new JSONObject(buf.toString());
} catch (Exception e) {
System.out.println(e.getMessage());
}
if (path.equals("/monitor")) {
//your Logic
//Use any other Library - I use GSON
Gson gson = new Gson();
String json = gson.toJson(POJO_OBJECT);
t.getResponseHeaders().set("Content-Type", "application/json");
t.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
t.getResponseHeaders().set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
t.sendResponseHeaders(200, json.length());
OutputStream os = t.getResponseBody();
os.write(json.getBytes());
os.close();
}
if (path.equals("/monitor")) {
//Your Logic
//Use any other Library - I use GSON
Gson gson = new Gson();
String json = gson.toJson(POJO_OBJECT);
//System.out.println(json);
t.getResponseHeaders().set("Content-Type", "application/json");
t.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
t.getResponseHeaders().set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
t.sendResponseHeaders(200, json.length());
OutputStream os = t.getResponseBody();
os.write(json.getBytes());
os.close();
}
}
}
}

Related

JAVA : how to send and receive Json String using HTTP from Client To Server and vice versa

client programming over sockets in java but im new in HTTP client-server apps .
however im trying to write client-server application which the client should be able to send messeges to server and hear the result back and they should be able to send and receive files .
what i've done so far is creating a Server using com.sun.net.httpserver ( which i dont know if is suitable or not , it was the only thing i could find a good tutorial for it ):
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
server.createContext("/test", new MyHandler());
server.setExecutor(null);
server.start();
}
static class MyHandler implements HttpHandler {
#Override
public void handle(HttpExchange t) throws IOException {
System.out.println(t.getHttpContext());
String response = "This is the response";
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
and i could successfully create a connection to this server using java.net.URL and java.net.HttpURLConnection .
but i dont know how should i send and recieve strings and files on both sides ! and i couldn't even find a good complete tutorial for that .
so now i wish someone to give me a simple example on how to do that ?
or if there is any good and easy to learn library i can use for this ? ( of course i need some tutorials first )
thanks in advance
This is an http server example that sends files.
http://www.rgagnon.com/javadetails/java-have-a-simple-http-server.html

How to upload a file of 750MB in JAVA, using jersey-client V2.13 (from a client to a server)?

Just before starting to explain you my problem, I would like to share with you the libraries' versions that I use and the server:
javax.ws.rs-api: 2.0.1
jersey-container-servlet: 2.13
jersey-media-multipart: 2.13
jackson: 2.4.3
I also use Apache Tomcat Server version 7.0.55.
So I coded that below:
/**
* On the client side.
*/
public void uploadAFile() {
Client client = ClientBuilder.newBuilder()
.register(MultiPartFeature.class)
.build();
WebTarget target = null;
try {
target = client
.target("https://blo-bla.rhcloud.com/rest")
.path("v1").path("upload");
} catch (IllegalArgumentException | NullPointerException e) {
LOG_TO_CONSOLE.fatal(e, e);
LOG_TO_FILE.fatal(e, e);
}
Builder builder = target.request(MediaType.TEXT_PLAIN);
builder.header("Authorization",
getValidBasicAuthenticationStrEncrypted());
FormDataMultiPart form = new FormDataMultiPart();
form.field("anotherParam", "Bozo");
String fileName = "/Users/drizzy/Documents/Divx/CaseDepartFolder/sample.avi";
File file = new File(fileName);
form.bodyPart(new FileDataBodyPart("file", file,
MediaType.APPLICATION_OCTET_STREAM_TYPE));
Response response = builder.post(Entity.entity(form,
MediaType.MULTIPART_FORM_DATA_TYPE));
LOG_TO_CONSOLE.debug(response.getStatus());
LOG_TO_CONSOLE.debug(response.readEntity(String.class));
}
/**
* On the server side.
*/
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.TEXT_PLAIN)
public String uploadFile(#FormDataParam("file") InputStream fileInputStream,
#FormDataParam("file") FormDataContentDisposition fileDisposition,
#FormDataParam("anotherParam") String str)
throws FileNotFoundException, IOException
{
System.out.println("str: " + str);
final String basePath = "/Users/drizzy/eclipse-workspace/tomcat7jbossews"
+ "/src/main/resources/uploads/";
final String fileName = fileDisposition.getFileName();
System.out.println(new StringBuilder().append("***** fileName ")
.append(fileName)
.toString());
final String filePath = new StringBuilder().append(basePath)
.append(fileName)
.toString();
System.out.println(filePath);
try (OutputStream fileOutputStream = new FileOutputStream(filePath)) {
int read = 0;
final byte[] bytes = new byte[1024];
while ((read = fileInputStream.read(bytes)) != -1) {
fileOutputStream.write(bytes, 0, read);
}
}
return "File Upload Successfully !!";
}
Which generates these exceptions at the client side:
Java Heap space error
and
Java binding Exception: Already connected
So my question is to know if somebody could please provide me an example of code with a client using jersey-client V2.13 which uploads a big file from the client to the server? Or even could telling me what is wrong in my code above?
Note: I only want to use jersey-client version V2.13 for handling that problem, so please do not provide me solutions using third party libraries or which do not use jersey-client version V2.13.
Finally I have found a solution to my problem:
1 - For fixing the "Already connected" Exception.
Java 7 introduced SNI support which is enabled by default. I have found out that certain misconfigured servers send an "Unrecognized Name" warning in the SSL handshake which is ignored by most clients... except for Java. As #Bob Kerns mentioned, the Oracle engineers refuse to "fix" this bug/feature.
As workaround, they suggest to set the jsse.enableSNIExtension property. To allow your programs to work without re-compiling, run your app as:
"-Djsse.enableSNIExtension=false"
Source of this information here.
The property can also be set in the Java code, but it must be set before any SSL actions. Once the SSL library has loaded, you can change the property, but it won't have any effect on the SNI status. To disable SNI on runtime (with the aforementioned limitations), use:
System.setProperty("jsse.enableSNIExtension", "false");
2 - For fixing the chunkedTransferMode's activation and java heap space error.
Java heap space error: I had to increase the jvm memory used by the client:
For doing that In eclipse, go to Run > Run Configurations ... > Select the client class > Arguments > VM arguments:
-Xms1024m -Xmx2500m -XX:+PrintFlagsFinal
Sources that I used myself for fixing that problem: source 1, source 2, source 3.
Regarding the fact of enabling the chunkedTransferMode, I did not need to do that, because I found in the documentation of jersey-client that the chunkedTransferMode was enabled by default in jersey-client V2.13.
In the end we pass these parameters to the JVM at the client side:
"-Djsse.enableSNIExtension=false" "your classes ..." -Xms1024m -Xmx2500m -XX:+PrintFlagsFinal
Ok it seems that the problem is a really large file (350Mb) and you are hitting various limits. Therefore I would suggest to address the problem in a different way.
Possible solutions:
Split the file on the client and upload it via "smaller" parts to the server where it is assembled back in original order.
Stream a file to the server: http://commons.apache.org/proper/commons-fileupload/streaming.html
I would prefer the 2. solution as it is probably the easiest to implement.
Hope this helps.

Newly-developed encoding issue with an Oracle Java program

My Java program (or rather, a part of it) sends a request to a webservice and receives rdf-strings including ancient Greek words in unicode. I wrote the program in netbeans and so far, there has not been a problem during run-time, both in the netbeans environment and outside as a standalone jar under Linux and Windows XP. Now, all of a sudden the Greek words in the rdf come back garbled like this:
á¼€
At first, I thought this was a Windows XP problem, but when checking under Windows 7 the problem persisted. I found out that I was running OpenJDK under Linux, and was since able to reproduce the issue using Oracle Java.
This is the relevant code (of course, I may have tunnel vision, so please tell me if you need more):
try {
HttpClient client = new DefaultHttpClient();
HttpGet get;
get = new HttpGet(URL+URLEncoder.encode(form, "UTF-8"));
HttpResponse response = client.execute(get);
if (201 == response.getStatusLine().getStatusCode()) {
HttpEntity respEnt = response.getEntity();
BufferedReader reader = new BufferedReader(new InputStreamReader(respEnt.getContent()));
StringBuilder sb = new StringBuilder();
char[] cbuffer = new char[256];
int read;
while ((read = reader.read(cbuffer)) != -1) {
sb.append(cbuffer,0,read);
}
//System.out.println(sb.toString());
rdf = new String(sb.toString().getBytes("UTF-8"),"UTF-8");
} else {
System.err.println("HTTP Request fehlgeschlagen.");
}
} catch (IOException e) {
System.err.println("Problem beim HTTP Request.");
}
The webservice is the Perseus morphology service, it can be found here: http://services.perseids.org/bsp/morphologyservice/analysis/word?lang=grc&engine=morpheusgrc&word=. Try "word=μῆνιν", for example. How or when the rdf is generated, I really don't know.
I would be very grateful for further insights!
Make sure the encoding of your strings is consistent from client to server and back again. In your case of course the servers response (rdf-strings) is most important (encoding serveside, decoding in your client code).
One thing concerning the client code you posted :
You are using the one argument constructor of InputStreamReader in this line:
BufferedReader reader = new BufferedReader(new InputStreamReader(respEnt.getContent()));
It will read from the inputstream using the VM (and systems) default charset, so the outcome will depend on the machine/VM you are running your client application on.
Try explicitly setting the charset using this constructor
new InputStreamReader(url.openStream(), "UTF-8")
See also API-doc.
Search your code for more uses of the one argument constructor of both InputStreamReader and OutputStreamWriter, which also uses the default encoding.
If you have no control over the server code (the webservice implementation), you can try to find out the answers charset like this:
Header contentType = response.getFirstHeader("Content-Type");
String charset= contentType.getValue();
(This is from the apache HttpClient API you seem to be using).
see also this Q on SO.

Large file transfer from HTTP server running Java Jersey Rest API

I am writing a web service using Java JDK 1.7 and Jersey Web service Framework. One of the things I need to provide is a way to allow authenticated clients to download certain large data files ( 1-3 GB). Ideally I would like this to be a pause and resume type downloadable option. I tried the jersey multi-part API and was able to get it to work on my client machine upto 400 MB but beyond that it ran into out-of memory issues. I am also worried that the server might fail when faced with simultaneous download requests. Any thoughts on how this can be done? Is Netty an option? Any pointers on how Netty can be integrated into a existing Jersey based web service? Are there other frame works available to help accomplish this? I do have to use java for the web service. Any pointers will be helpful.
If you are getting stuck on out-of-memory issues, you should check how you are handling the data you are downloading. If you are using Jersey's ClientResponse, make sure you are using getEntityInputStream() and not getEntity(). This way, you can stream the data, write it to file, and toss it aside, rather than letting it build up in the Java heap space.
I can't really speak about your simultaneous download concerns, but if you are using the web services framework, then it should be handled properly.
For both issues, more info on your specific implementation, especially code, will help you get a better response.
The server and the client must both support HTTP chunked encoding which allows one to stream data using HTTP. The code below should work with Jersey 2.11.
For downloading large files, try this on the server:
#GET
#Path("/files/{fileName}")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public StreamingOutput getFile(#PathParam("fileName") final String fileName) throws Exception {
//create instance of StreamingOutput here
return streamingOutput;
}
Try this for a client GET request using steams to download a file.
public String getFileReq(File outFile) throws IOException {
client = ClientBuilder.newClient(new ClientConfig());
client.property(ClientProperties.REQUEST_ENTITY_PROCESSING, "CHUNKED");
WebTarget target = client.target(URI)
OutputStream fileOutputStream = new FileOutputStream(outFile);
InputStream fileInputStream = target.request().get(InputStream.class);
writeFile(fileInputStream, fileOutputStream);
}
public static void writeFile(InputStream fileInputStream, OutputStream outputStream) throws IOException {
try {
byte[] buffer = new byte[1024];
int bytesRead;
while((bytesRead = fileInputStream.read(buffer)) !=-1) {
outputStream.write(buffer, 0, bytesRead);
}
fileInputStream.close();
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
outputStream.close();
}

Post to a site using Java, navigating past the 'i agree' redirect

I am trying to visit a site, and get the request to be processed to follow the redirect.
i visit the i agree site, but it doesnt seem to continue past that, and keeps redirecting me
Here is my code:
public static void main(String[] args)
{
System.out.println("results");
//String targetConfirmation18 = "";
URL url;
HttpURLConnection connection;
OutputStreamWriter osw = null;
BufferedReader br = null;
String line;
try {
url = new URL("");
//url = new URL(targetConfirmation);
connection = (HttpURLConnection)url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
osw = new OutputStreamWriter(connection.getOutputStream());
osw.write("");
osw.flush();
br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException ioe) {
// nothing to see here
}
}
}
I suspect that you are violating the Tabcorp Terms of Service. They say:
You may, using an industry-standard web browser, download and view the Content for your personal, non-commercial use only.
and
All rights not expressly granted herein are reserved.
The site sets cookies after you do post on 18+ url. You must remember them and submit with next requests. You can easily figure it out with FireBug.
As a result, you will need to use more advanced HTTP client than simple URL. For example, Apache HTTP Client that allows cookie manipulation.
This section in HTTP Client Tutorial specifically covers cookies.
I am pretty sure that your problem here is the HTTP session.
When you surf to the site using browser the server creates HTTP session and sends its ID as one of the cookies. Then browser sends the cookies back on each request, so server can recognize that this is the existing session.
I think that server always redirects you to 18+ page when session is unknown.
So, why the session is unknown in your case? It is because all your requests are independent. You should do as a browser. Do not start from posting to 18+ confirmation page. Start from HTTP get that will redirect you to this page. Take cookies from response header Set-Cookie and send the cookies back using request header "Cookie".
You can also use higher level tools like Jakarta HTTP client that does this work for you automatically, but it is a good exercise to implement it yourself. I tried this technique several times and saw that it works also with standard HttpUrlConnection.
BTW, I hope that this is not your case but sometimes you have to mimic the User-Agent: present yourself as one of the known browsers. Otherwise some sites redirect you to page that says that your browser is unsupported.
Good luck.

Categories