Is there a way to set the default buffer size for JSPs in Tomcat? I know I can set them on every page, but am hoping there's a global option somewhere.
Short answer: No.
Long answer: Perhaps, with some hacking...
You'd have to build Tomcat yourself after editing this class: Jasper constants
...or you can do a Perl pie, and edit all your JSPs all at once. Back-up first as this edits in-line:
For directives without the buffer set:
/usr/bin/perl -pi -e 's|<%# page|<%# page buffer="new" |g' `find . -type f -name '*.jsp'`
For already-set buffers:
/usr/bin/perl -pi -e 's|buffer="old"|buffer="new"|g' `find . -type f -name '*.jsp'`
(If your directives are inconsistent with the above, e.g. more/less whitespace, please use more regexp magic to make it work)
Your problem elsewhere on the web: http://www.theserverside.com/discussions/thread.tss?thread_id=24768
HTH
EDIT: To lift the comments discussion to this answer - this might be what you're after
When you're stuck with a legacy application even without separation of processing (controller) and view (jsp), you should limit your processing to the very first instructions on a jsp, e.g. right on top. There you're even free to redirect (e.g. send back response code 302), let alone signal errors with the correct error code. That said, you should avoid presenting 500 style errors to your customers anyway. Rather deliver a nice looking html page (200), displaying a helpful error message to the customer. Applications should display their errors on their level, not on a protocol level.
I remember, back in the last century, to have worked on such an application myself. We have experienced some platform differences: One platform didn't buffer even the first byte but immediately sent it back to the customer, rendering our redirection attempts (code 302) useless, as the 200-code header was already on it's way. The only thing that helped was to make sure that not a single byte could have been sent prior to the processing. As we've needed some taglibs, we've had to eliminate the linebreaks between taglib instructions. There's two ways to do this:
Instead of
<%# taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%# taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
<% /* your processing instructions here */
response.sendRedirect("somewhere.jsp") %>
write
<%# taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"
%><%# taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt"
%><% /* your processing instructions here */
response.sendRedirect("somewhere.jsp") %>
or use jsp comments to eliminate line breaks:
<%# taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %><%--
--%><%# taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt"%><%--
--%><% /* your processing instructions here */
response.sendRedirect("somewhere.jsp") %>
This might look ugly but greatly reduces the danger of the server flushing the buffer - no matter how big it might be.
Hope this helps.
This is what was answered prior to / during the comments discussion
The Tomcat docs for the http connector have bufferSize, socketBuffer and several more options for the nio installation - some for input- and some for output streams. The AJP connector seems not to be that configurable (you need the ajp connector if you use Apache/mod_jk).
I hope that the buffer you're looking for is among these...
EDIT: (The comment space has been too small, so I chose to add some more information regarding your comment that you use AJP here:)
The wisdom about buffer sizes seems to be implemented (from a brief look at the tomcat 6.0.18 source code) in org.apache.catalina.connector.OutputBuffer and in org.apache.catalina.connector.Response. Of particular interest is this piece of code (from Response):
/**
* Set the Connector through which this Request was received.
*
* #param connector The new connector
*/
public void setConnector(Connector connector) {
this.connector = connector;
if("AJP/1.3".equals(connector.getProtocol())) {
// default size to size of one ajp-packet
outputBuffer = new OutputBuffer(8184);
} else {
outputBuffer = new OutputBuffer();
}
outputStream = new CoyoteOutputStream(outputBuffer);
writer = new CoyoteWriter(outputBuffer);
}
Basing my judgement on this piece of code, it seems that increasing buffer size might not really be helping your issues. Not that I would like to say that it doesn't help... Did you measure actual performance when you increase buffer size from jsps? Does it help to do so?
With the knowledge of this point of contact you might suffice by either patching the tomcat source or by adding a filter to your web application or tomcat container configuration that tweaks the buffer size according to your needs. (I'd prefer the filter over the tomcat patch any time)
Another idea that comes to my mind is: If you use any templating system (like tiles, as you are mentioning jsp, but velocity or others come to mind) you shouldn't have too many points where you'd have to set the buffer size from jsps. In systems I've worked on I probably would guess that around 10 basic layout templates would be affected (independent of project size).
I hope that this addition helps...
Related
I have a very simple java applet, that Im using source code from the docs.oracle(http://docs.oracle.com/javase/tutorial/deployment/applet/getStarted.html) site that should work, and it works in eclipse just fine, it's getting it onto the page that's the problem. The file is on a localhost server at localhost/applet/applet.html and I have the file JavaQuiz.jar in the same directory. My html file is as follows.
<hmtl>
<applet codebase="localhost/applet/"
code = 'JavaQuiz.jar'
archive = 'JavaQuiz.jar'
width = 300
height = 300 />
</html>
Is there something Im missing? Or need to change? I look forward to any help that could be given, and please try to explain it more than telling me the answer so I can learn. :D
This is what is in the java colsole
Java Plug-in 10.5.1.255
Using JRE version 1.7.0_05-b05 Java HotSpot(TM) Client VM
User home directory = C:\Users\Jihoon
c: clear console window
f: finalize objects on finalization queue
g: garbage collect
h: display this help message
l: dump classloader list
m: print memory usage
o: trigger logging
q: hide console
r: reload policy configuration
s: dump system and deployment properties
t: dump thread list
v: dump thread stack
x: clear classloader cache
0-5: set trace level to
plugin2manager.parentwindowDispose
The Chrome developer help thing doesn't show any problems. And when I click details on the applet it just says classnotfounfexception: JavaQuiz
<html>
<applet
archive="http://localhost/applet/JavaQuiz.jar"
code="JavaQuiz.class"
width = 300
height = 300 />
</html>
I think the biggest problem is not having the http:// I'm not entirely sure about the other parameters. Play around with that.
So in your case change codebase="localhost/applet/" to codebase="http://localhost/applet/"
The code attribute should point to a fully qualified class name, not to a jar.
Also you should have an eye on localhost... this means that the j.jar is located in a folder called localhost in the same directory that the html is in. Is that true? Or do you mean http://localhost:80/applet/ or /applet/
<hmtl> should be <html>
The mandatory "code" attribute (which is missing in your example) should point to the class which you intend to run (the one extending JApplet). Something like:
<html>
<applet codebase="localhost/applet/" code="yourpackage.YourApplet.class"
code = 'JavaQuiz.jar'
archive = 'JavaQuiz.jar'
width = 300
height = 300 />
</html>
http://localhost/applet/JavaQuiz.jar will not work at time of deployment.
<html>
<applet
codebase="."
archive="JavaQuiz.jar"
code="JavaQuiz"
width = 300
height = 300 >
</applet>
</html>
Since the code base points to the 'current directory' this will work for the applet while on localhost as well as deployed live.
Points, some of which have already been mentioned:
The code attribute should be the fully qualified class name of the applet class, without .class on the end.
The applet element cannot be 'self closed' - always use </applet> to close the element.
If omitted the code base defaults to the directory the HTML is in, so putting codebase="." is redundant. It should also work without it.
What techniques could I use to modify a set of JSPs to measure the overall performance of the JSPs and then to further narrow down and identify the specific areas within the JSP where the most time is spent?
My current approach is to simply use a scriptlet and System.currentTimeMillis():
top of JSP
<%
StringBuilder result = new StringBuilder();
long startTime = System.currentTimeMillis();
%>
... JSP code here
<%
long duration = System.currentTimeMillis() - startTime;
if (duration > 100L) { //over 100 ms
result.append("JSP page took "+duration+"ms");
}
%>
<!-- <%=result%> -->
But the problems with this are:
polluted JSPs with this performance code,
copy pasted code in several JSPs,
does not work well when JSPs are included with <%# include ... %> since the result variable is already be defined in multiple JSPs.
#1 - the golden rule - don't put any logic in JSPs. write custom tags. extract any logic into java code. JSP is the presentation layer.
#2 - run servlet container in a profiler (like jvisualvm or even better: yourkit). This will tell you exactly where the time is spent
NOTE - nowadays you don't need to "run an app in a profiler" - if using JDK6+ you can pop open yourkit or jvisualvm (comes with JDK) and attach magically while it's running. it's really handy.
Is there a way to remove blank lines from server response? I have tried out:
<init-param>
<param-name>trimSpaces</param-name>
<param-value>true</param-value>
</init-param>
and
<%# page trimDirectiveWhitespaces="true"%>
which didn't solve the issue properly since in init param method it removed even space between words, 2nd method didn't work either since it needs java servlet version to be 2.5.
Your advice will be very helpful ..
you should create a filter-servlet that remove blank lines and chained the response to your servlet.
when the server convert the JSP page to servlet it add implicitly blank lines (\n).
add out.clear() befor writing data to clear out object.
Add the following directives to your page and the lines should disappear:
<%# page contentType="text/xml" %>
<%#page pageEncoding="UTF-8"%>
<%# page trimDirectiveWhitespaces="true"%>
I think, you should use an IDE like eclipse. Where you can just select the whole code and format it and follow all java syntax guidelines by just right clicking and seletcing a few options.
Please use good IDE's all of them will help you follow good guidelines and make your work simpler and easier to read and understand
I've got a JSP page that I want to return a fragment of HTML. The trouble is that whenever I request the JSP, something is attempting to make the HTML more valid by wrapping <html> tags around it. I don't want it to do this though as it will be used in a variety of other places.
For an example, the following JSP:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<script src="${applicationConfig.javascriptUrl}update.js" language="javascript" type="text/javascript"></script>
<p>Wibble</p>
Will result in the following HTML:
<html xmlns="http://www.w3.org/1999/xhtml"><head></head><script src="http://fisher.mycompany.com:8080/my-app/includes/js/update.js" language="javascript" type="text/javascript"></script>
<p>Wibble</p></html>
I really don't want those <html> & <head> tags there and would like to get rid of them but have no idea where this is happening to turn it off. Does anyone have any clues?
* Edit *
To give a little more information on what I am trying to achieve. This JSP will check a variety of things and form a piece of HTML. This HTML can then be included into other applications via a web service call.
Servlets can return any content type including javascript and images, not just HTML. Tomcat should not wrap jsps in extraneous tags. I put the snippet you suggested in a jsp, minus the taglib which I don't have set up, and got back exactly the HTML that I put in.
Can you tell us more about your environment? Are you using tomcat? Are you using some kind of framework?
Servlets are HTML factories. They expect to send a valid HTML page down to a browser to be rendered. You can't "get rid of it" without breaking the whole model.
Your original concept of sending a snippet that's "used in a variety of other places" is flawed. You sound like to want to set some data that might be used in other places - that's valid - but I don't see how wrapping it in markup matters.
Only the JSP should be using the marked up data. JSPs are all about display. I'd rethink what you're doing and attack how you want to share the data, not the markup.
One approach it might work,
Create HTML files as you required valid HTML,
and use servlet to returns response, servlet should read HMTL File and return
its contents as String, like XML respones from servlet
hopes thats helps
This may sound totally stupid, but is a case of real life :(
I'm able to display a HTML table with a "virtual" link name.
Something like this:
Xyz description document.doc
Xyz description documentB.doc
Xyz description documentC.doc
This doc id represents an id in the database ( for these docs are stored in a blob as byte[] )
Anyway. I'm able to get that id, query the database and retrieve the byte[] ( and even store it in a tmp file )
What I can't figure out how to do, is, that when the user click on the link ( and after I perform the db retrieval ) "serve" the byte[] to the user.
Now the very worst part, and what makes me ask this question here is, I need to do this with JSP only ( no servlet ) and without 3rd party libraries ( just... don't ask me why I hate it too )
So. How do I serve in a jsp the binary content of a byte array stored in the server file system
My first guest is:
<%
InputStream read // read the file form the fle system
response.getOutputStream().write( theBytesReader );
%>
Am I close to the solution?
Would this work to the client as if he had clicked really in the server for a real file?
Thanks in advance.
To the point, just write the same code in JSP as you would do in a Servlet class. You can practically copypaste it. Only ensure that you are not writinig any template text to the stream, this includes linebreaks and whitespace outside the scriptlets. Otherwise it would get written to the binary file as well and corrupt it.
If you have multiple scriptlet blocks, then you need to arrange them so that there's no linebreak between the ending %> of a scriptlet and the starting <% of the next scriptlet. Thus, e.g.
<%#page import="java.io.InputStream" %><%
//...
%>
instead of
<%#page import="java.io.InputStream" %>
<%
//...
%>
You need to set the MIME type in the HTTP response like below in addition to the sample code you provided.
response.setContentType("application/octet-stream");
Note, the application/octet-stream MIME type is used to indicate a binary file.
Please, please, please don't do this.
You're doing a disservice to your users.
HTTP is amazingly rich in terms of what it can do with files. Caching, chunking, random access, etc.
Take a look at something like FileServlet, and hammer that to fit. Yes, it's a Servlet, rather than a JSP, but this is what you want to do to be a good HTTP citizen.
Some containers have other options you can use, you can hack Tomcats DefaultServlet, etc.
Something like this...
InputStream instr = null;
try {
instr = new BufferedInputStream( new FileInputStream("file.txt") );
for(int x=instr.read(); x!=-1; x=instr.read()){
out.write(x);
}
} finally {
out.close();
if( instr != null) instr.close();
}
You will need this as the response to the click (either on a page reload or in another jsp file).
There are better buffering solutions you can do with the write using byte arrays rather than one at a time... I will leave that for you.
Sorry you are stuck in JSP scriptlet land...Hope this helps.