JSP function and out.close()

W

Winston Kotzan

Hello,

I have a function within an include page (common_func.jsp) like this:

<%!
public void DisplayError(String ErrMsg) {
%>
<html>
<head><title>Application Error</title></head>
<body>
<h1>Application Error:</h1>
<h3> out.print(ErrMsg); </h3>
</body>
</html>
<%!
out.close();
}
%>

This function is common on all my pages, so I call it by having an include
like this at the top of each page:
<%@ include page="common_func.jsp" %>

The problem is that when that function is called, the "out" variable is not
recognized. I think the problem may be with scope. How can I access the
Java "out" object from within my function?

Thanks.
 
P

Paul

Try passing it as another argument. I think its type is JspWriter.
You probably don't want to close it there though, since
1) closing it will mean anything done after that function can't write output
2) it will automatically close when it goes out of scope (I believe, might
check the docs on it)
--Paul
 
T

toxa26

It wont get closed when it goes out of scope (JspWriter doesn't
override finalize()), but it will be called by the servlet code
generated by the jsp container. You shouldn't do this because the jsp
generated code will make a call to close again. You wont see it on the
screen, but you will see it in your server log files. Not pretty. If
you still want to do this, you must pass a JspWritter object to your
method. Again, think of how this gets translated into servlets. You
have your service() method, which is where all your jsp stuff is, and
then you have your <%!DisplayError%> method. This later method is a
public method of the generated servlet class. It behaves just like any
other public method behaves in java.

Hope this helps,
Anton
 
J

John C. Bollinger

Winston said:
I have a function within an include page (common_func.jsp) like this:

<%!
public void DisplayError(String ErrMsg) {
%>
<html>
<head><title>Application Error</title></head>
<body>
<h1>Application Error:</h1>
<h3> out.print(ErrMsg); </h3>
</body>
</html>
<%!
out.close();
}
%>

This function is common on all my pages, so I call it by having an include
like this at the top of each page:
<%@ include page="common_func.jsp" %>

The problem is that when that function is called, the "out" variable is not
recognized. I think the problem may be with scope. How can I access the
Java "out" object from within my function?

I'm somewhat surprised that compiles at all. It's purest luck if it
does, as the code is horribly broken. The main problem is that JSP
declarations (<%! ... %>) must contain one or more *complete*
declarative statements. Neither declaration contains a complete
statement. Moreover, even if the page compiles, it will not (in a
compliant container) do what you expect: the code generated for the
template text between the two declarations will will not be anchored
between the two declarations, but rather will appear in the
_jspService() method with the rest of the page body.

As for the "out" implicit object, it is not available in declarations,
only in scriptlets and expressions. This is because JSP declarations
result in class-level declarations when the JSP is translated into a
servlet. The implicit objects are per-request entities, and thus cannot
be available outside the scope of the _jspService method.
 
W

Winston Kotzan

Since I started out dynamic website programming in PHP and ASP, perhaps I am
using the wrong approach for my JSP pages. In that case, what would be the
preferred way of building recycleable functions among pages? In particular,
how could this be done and allow the page to safely output an error message
then terminate from the recycled function?

Thanks for the help.

--
Winston Kotzan
http://www.wakproductions.com/


PS- I'm an IU fan. Go Hoosiers!
 
M

Malte

John said:
I'm somewhat surprised that compiles at all. It's purest luck if it
does, as the code is horribly broken. The main problem is that JSP
declarations (<%! ... %>) must contain one or more *complete*
declarative statements. Neither declaration contains a complete
statement. Moreover, even if the page compiles, it will not (in a
compliant container) do what you expect: the code generated for the
template text between the two declarations will will not be anchored
between the two declarations, but rather will appear in the
_jspService() method with the rest of the page body.

As for the "out" implicit object, it is not available in declarations,
only in scriptlets and expressions. This is because JSP declarations
result in class-level declarations when the JSP is translated into a
servlet. The implicit objects are per-request entities, and thus cannot
be available outside the scope of the _jspService method.
This kind of code actually compiles and works in Oracle's OC4J j2ee
container. Fails in Tomcat.
 
J

John C. Bollinger

I said:
I'm somewhat surprised that compiles at all.

[...]

And that's before we even get to the question of closing "out", which is
never a good idea. You may flush it, but closing it is simply begging
to have your JSP container start throwing exceptions. What is the
purpose of closing it, anyway?


John Bollinger
(e-mail address removed)
 
J

John C. Bollinger

Winston said:
Since I started out dynamic website programming in PHP and ASP, perhaps I am
using the wrong approach for my JSP pages. In that case, what would be the
preferred way of building recycleable functions among pages? In particular,
how could this be done and allow the page to safely output an error message
then terminate from the recycled function?

You can declare a complete method with a JSP declaration, and you can
invoke that method from within the page body. You cannot, however, use
template text to define any part of the method. That would meet your
needs except for the part about terminating the page evaluation. If you
want to do that, then custom tags are an excellent option.
Alternatively, instead of using a custom tag you can forward the request
to another resource by means of the <jsp:forward> standard action. If
the resource you forward to is a JSP then you can (naturally) use
template text to define some or all of its behavior. Do note the
important distinction between a forward and a redirect: the former
happens entirely within the JSP container, using the same request and
response objects, whereas the latter involves an additional HTTP round
trip and therefore new request and response objects.
 
J

John C. Bollinger

This kind of code actually compiles and works in Oracle's OC4J j2ee
container. Fails in Tomcat.

As far as I know, J2EE does not require that JSP containers _diagnose_
the error of the incomplete declarations. A container may conceivably
accept illegal code and do something with it, but that does not make the
code legal. The semantics of illegal code are not defined by the spec,
so the container may do anything it wants with such (including starting
World War III, as the saying goes in another computing forum). Such
illegal code is likely to behave differently in different containers,
and possibly from one version to another of the same container.

If you mean that OC4J makes the implicit objects available inside
(legal) JSP declarations then I suggest you verify your claim. I can
imagine ways in which this might be achieved, but all of them either
fail to be thread safe (meaning that they will result in corrupted pages
in some circumstances) or scale poorly.
 
W

Winston Kotzan

I thought out.close() is an equivalent of Response.End in ASP. Is that
correct?





John C. Bollinger said:
I said:
I'm somewhat surprised that compiles at all.

[...]

And that's before we even get to the question of closing "out", which is
never a good idea. You may flush it, but closing it is simply begging to
have your JSP container start throwing exceptions. What is the purpose of
closing it, anyway?


John Bollinger
(e-mail address removed)
 
J

John C. Bollinger

Winston said:
I thought out.close() is an equivalent of Response.End in ASP. Is that
correct?

Apparently not. I don't know any ASP, but there is no way in JSP /
servlets to safely express the idea that what has been written to the
response so far is all that ever should be written. The concept is
incompatible with the JSP / servlet architecture, which, among other
things, permits filters to be specified for JSPs; such filters may do
all manner of operations on the response, and in particular they may
write additional data to it.

A JSP can stop producing output before the end of its body by executing
a return statement in scriptlet code, by executing a <jsp:forward>
standard action, or by executing a custom action (with use of a tag
library) that skips evaluation of the rest of the page as part or all of
its effect. Closing the output stream without doing one of those
things, if it has any effect at all, is pretty much guaranteed to make
page evaluation fail with an IOException. Closing the output stream
_and_ doing one of those things is likely to make the container throw
exceptions internally, which may well result in the server failing to
serve the page with a mysterious "internal server error".
 
Joined
Nov 27, 2007
Messages
1
Reaction score
0
Response.End()

The misunderstanding here is that in ASP (and ASP.Net), Response.End() terminates all further EXECUTION. It doesn't just stop output, it stops the entire script from executing. It's like exit(0);.

So far as I've been able to determine, there is not a similar method available in JSP. You'll have to throw an exception there, and have a try/catch block around the code that calls it. Or if you're not in a method you can simply return.

For instance, in ASP:
<title>Test page</title>
<%
If Request("REQUEST_METHOD") <> "POST" Then
Response.Write("Error: You must post to this page.")
Response.End()
End If
%>
<font size=4>Hello World</font>

Is translated to:
<title>Test page</title>
<%
If (!request.getMethod().equalsIgnoreCase("POST")) {
out.write("Error: You must post to this page.")
return;
}
%>
<font size=4>Hello World</font>

And likewise:

<%
try {
testError("foo");
out.write("Hello world");
} catch (Exception e) {
out.write(e.getMessage());
return; // note we're not in a method here, this code gets executed when the page loads
}

public void testError(String val) throws Exception {
if (val.length() > 0) throw new Exception("Error: " + val + " found.");
}

%>

Charles.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,263
Messages
2,571,062
Members
48,769
Latest member
Clifft

Latest Threads

Top