Object suddenly missing from HttpServletRequest - java

I print a list directly in the servlet using the print writer and the list prints.
When I try to put in the jsp however the list doesn't print whether I use JSTL or scriptlets.
I tried to test in JSTL and scriptlet if the object is null and turns out that it is!
Why does this happen and how can I fix this?
Servlet code that works
for (Artist artist:artists){
resp.getWriter().println(artist.getName());
}
Servlet code that puts object in the request
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("com/helloworld/beans/helloworld-context.xml");
ArtistDao artistDao = (ArtistDao) ctx.getBean("artistDao");
List<Artist> artists = null;
try {
artists = artistDao.getAll();
} catch (SQLException e) {
e.printStackTrace();
}
req.setAttribute("artists", artists);
try {
req.getRequestDispatcher("index.jsp").forward(req, resp);
} catch (ServletException e) {
e.printStackTrace();
}
scriptlet code that suddenly finds the object null
<%
List<Artist> artists = (List<Artist>) request.getAttribute("artists");
if (artists == null) {
out.println("artists null");
}
else {
for (Artist artist: artists){
out.println(artist.getName());
}
}
%>
Even the jstl code seems to agree
<c:if test="${artists eq null}">
Artists are null
</c:if>
<c:forEach var="artist" items="${artists}">
${artist.name}
</c:forEach>
For my app I am using weblogic, spring 2.5.6 and ibatis.

I think it depends on the web server. But without changing your previous directory structure,
try putting the list in session like this
req.getSession(false).setAttribute("artists", artists);
and in your jsp,
write
List<Artist> artists = (List<Artist>) request.getSession(false).getAttribute("artists");
I think my approach will work for all web servers.

Maybe the app server is resetting your request object. You can work around this by creating a new request object, that wraps your original request, and pass that to the reqest dispatcher.
e.g.
MyHttpRequest myRequest = new MyHttpRequest(req);
myRequest.setAttribute(...);
req.getRequestDispatcher("index.jsp").forward(myRequest, resp);
And the MyHttpReqest code:
class MyHttpRequest extends HttpServletRequestWrapper
{
Map attributes = new HashMap();
MyHttpRequest(HttpRequest original) {
super(original);
}
#Override
public void setAttribute(Object key, Object value) {
attributes.put(key, value);
}
public Object getAttribute(Object key) {
Object value = attributes.get(key);
if (value==null)
value = super.getAttribute(key);
return value;
}
// similar for removeAttribute
}

I just discovered inadvertently while trying to fix my directory structure in WebContent/
My previous directory structure was
WEB-CONTENT/
- META-INF/
- WEB-INF/
index.jsp
Then I tried to create a folder jsp in WEB-CONTENT and placed index.jsp there. It works!
My current directory structure now is
WEB-CONTENT/
- META-INF/
- WEB-INF/
- jsp/
-index.jsp
I don't know why it works but it did.
Anyone here with any idea why?

Related

Exception after reading values from jsp page

I am inserting values into database but I am getting UIException here is my code sample,
public void createTeacherInfo(HttpServletRequest request) {
try{
TeacherInfo teacherInfo= new TeacherInfo();
request.getParameter("flowName");
DateFormat df = new SimpleDateFormat("dd-mm-yyyy");
String tId= request.getParameter("teacherId");
teacherInfo.setTeahcerId(Integer.parseInt(tId));
//teacherInfo.setTeahcerId(Integer.parseInt(request.getParameter("teacherId")));
teacherInfo.setTeacherName(request.getParameter("teacherName"));
/*teacherInfo.setDob(df.parse(request.getParameter("dob")));
teacherInfo.setDoj(df.parse(request.getParameter("doj")));*/
teacherInfo.setTeacherEducation(request.getParameter("education"));
teacherInfo.setPreviousEmployeDetails(request.getParameter("prevdetails"));
//teacherInfo.setYearOfExper(Integer.parseInt(request.getParameter("experience")));
teacherInfo.setTeahcherPhoto(request.getParameter("photo"));
teacherInfo.setTeacherEmail(request.getParameter("email"));
System.out.println(tId);
System.out.println("TeacherId");
pupilInfoManagementBusinessService.createTeacherInfo(teacherInfo);
}catch (BusinessException e) {
webLayerLogger.error(CommonUtils.getStackTrace(e));
throw new UIException(e,UIMessageHelper.getLocalValue("exception while Inserting data"));
}
}
In this method after reading all values it will go to service method , Here is service class method,
#Override
public void createTeacherInfo(TeacherInfo teacherInfo) throws BusinessException {
try {
pupilInfoManagementDataService.createTeacherInfo(teacherInfo);
}catch (Exception e) {
businessServiceLogger.error(CommonUtils.getStackTrace(e));
throw new BusinessException(this.getClass(), e, e.getMessage());
}
}
My problem is values are reading but not inserting to database. Please help me in this .
I'll bet the html form for this includes a file upload for the photo. When a form includes a file upload, then request.getParameter will not work any longer (the values will always be null). When you do a file upload you have to use Apache Commons File Upload library to retrieve the parameters from the request, or you can use request.getPart (if you are on the latest version of your servlet container).

Displaying streams in DIV

I am running some terminal(or command prompt) commands through my servlet as below
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String[] command =
{
"zsh"
};
Process p = Runtime.getRuntime().exec(command);
new Thread(new SyncPipe(p.getErrorStream(), response.getOutputStream())).start();
new Thread(new SyncPipe(p.getInputStream(), response.getOutputStream())).start();
PrintWriter stdin = new PrintWriter(p.getOutputStream());
stdin.println("source ./taxenv/bin/activate");
stdin.println("python runner.py");
stdin.close();
int returnCode = 0;
try {
returnCode = p.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println("Return code = " + returnCode);
}
class SyncPipe implements Runnable
{
public SyncPipe(InputStream istrm, OutputStream ostrm) {
istrm_ = istrm;
ostrm_ = ostrm;
}
public void run() {
try
{
final byte[] buffer = new byte[1024];
for (int length = 0; (length = istrm_.read(buffer)) != -1; )
{
ostrm_.write(buffer, 0, length);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private final OutputStream ostrm_;
private final InputStream istrm_;
}
This is displaying the result after executing terminal commands in a new window, I want to avoid that and pass these stream values back to JSP page and display the same in a div.
How to do that?
Static import
First of all, you can define a scriplet with <%= and %> like explained here and here.
Instead of copying the whole code, you can statically import the .jsp page like so:
<%# include file="YourPage.jsp" %>
Link.
To call the page at runtime instead of at the server-side you do:
<jsp:include page="YourPage.jsp"/>
But this doesn't yield a huge advantage over static importing.
Link
You can also declare your function and then use it throughout your webpage by using <%! and %> like shown here.
If you do any of the methods above, your function will (can) be imported only when the page initially loads (server-side). (To be absolutely correct, <jsp:include is called at runtime in theory but in practice it simulates a request without actually making a complete round-trip: server > browser > server > browser).
Dynamic import
For dynamic importing or loading, you have to resort to jQuery (JavaScript) to load your JSP page client-side.
Please refer to this question: How do I inject another JSP page into a <div> when clicking a link?
You could simply do:
function changeContent() {
$('#content').load('YourPage.jsp');
}
You can find other examples here:
Display another jsp content in current jsp page upon a hyperlink click
CodeRanch
To quote the answer from the last link:
That's something to do with Ajax, Jquery can do that. You can use javascript getElementByID or use Jquery's build_in $("sub_banner") syntax to change the div's content.

Calling application.getRealPath() from within a class in JSP

I am writing a class in JSP to retrieve a bunch of config values from an XML file. My plan is to have a class "XMLConfig" that loads in the values from the file, and then uses access methods to get at the values in the config object.
My problem is that i cannot seem to call application.getRealPath() from within the class, since eclipse tells me that "application cannot be resolved". I suspect that I must change "application" to something else but I am unsure what.
My code for the class:
<%!
//Config object
public class XMLConfig {
public boolean loadConfigFile(String strName) {
String XMLfileName = application.getRealPath(strName);
try {
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = null;
doc = db.parse(XMLFileName);
}catch(Exception e)
{
System.out.println(e.getMessage());
return false;
}
return true;
}
}
%>
application isn't a global var. If you want to use it in your method then you'll need to pass it as a parameter.
Not sure why you're defining the class within the jsp though instead of just creating a 'normal' java class.
That's a job for a servlet instead of JSP. Create a class which extends HttpServlet and implement the doGet() method as follows:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String strName = getOrDefineItSomehow();
Document doc = loadConfigFile(getServletContext().getRealPath(strName));
// Do whatever you want with it and then display JSP page.
request.getRequestDispatcher("/WEB-INF/config.jsp").forward(request, response);
}
Map this servlet in web.xml on an url-pattern of for example /config and invoke it by for example http://example.com/context/config. It'll run the code in doGet().
See also:
Beginning and intermediate JSP/Servlet tutorials
How to avoid Java code in JSP?
Hidden features of JSP/Servlet

JSP helper class for printing content

I have a question on code reuse in JSP. I have a JSP page example.jsp that issues a call to a database and gets the results. I have a java class HelperClass.java that accepts a record and prints out the different fields
response.getWriter().println
Now my JSP page has HTML as well and the problem is the content printed out by the HelperClass appears before the content in the JSP page. E.g.
<body>
This is the first line <br/>
HelperClass.printdata("second line");
</body>
output is
secondline This is the first line
Is this a known issue. What is the best way to design an HelperClass for a JSP page that prints content out to the page. Any pointers would be greatly appreciated.
Just do not use a "HelperClass to print data". This makes no sense. There you have EL for.
${bean.property}
That's all. Use a servlet to control, preprocess and postprocess requests. Use taglibs (e.g. JSTL) and EL to access and display backend data.
Here's a basic kickoff example of a Servlet which preprocesses the request before display in JSP:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Person> persons = personDAO.list(); // Get list of persons from DB.
request.setAttribute("persons", persons); // So it's available as `${persons}` in EL.
request.getRequestDispatcher("/WEB-INF/persons.jsp").forward(request, response); // Forward to JSP for display.
}
Here, the Person is just a Javabean class which represents a real world entity.
public class Person {
private Long id;
private String name;
private String email;
private Integer age;
// Add/generate getters and setters here.
}
The PersonDAO#list() method just returns a List of Person objects from the DB:
public List<Person> list() throws SQLException {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
List<Person> persons = new ArrayList<Person>();
try {
connection = database.getConnection();
statement = connection.createStatement("SELECT id, name, email, age FROM person");
resultSet = statement.executeQuery();
while (resultSet.next()) {
Person person = new Person();
person.setId(resultSet.getLong("id"));
person.setName(resultSet.getString("name"));
person.setEmail(resultSet.getString("email"));
person.setAge(resultSet.getInteger("age"));
persons.add(person);
}
} finally {
if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
return persons;
}
Map the servlet in web.xml on an url-pattern of /persons. The JSP is hidden in /WEB-INF so that nobody can access it directly without requesting the servlet first (else one would get an empty table).
Now, here's how persons.jsp look like, it uses JSTL (just drop jstl-1.2.jar in /WEB-INF/lib) c:forEach to iterate over a List and it uses EL to access the backend data and bean properties. The servlet has put the List<Person> as request attribute with name persons so that it's available by ${persons} in EL. Each iteration in c:forEach gives a Person instance back, so that you can display their proeprties with EL.
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
<table>
<c:forEach items="${persons}" var="person">
<tr>
<td>${person.name}</td>
<td>${person.email}</td>
<td>${person.age}</td>
</tr>
</c:forEach>
</table>
Call it by http://example.com/contextname/persons. That's all. No need for a "HelperClass to print data" ;) To learn more about JSTL, check Java EE tutorial part II chapter 7 and to learn more about EL, check Java EE tutorial part II chapter 5. To learn more about stuff behind PersonDAO, check this article.

Java/JSP Image upload. Where to keep these image files?

I am writing a simple application that lets a user upload images. After the upload, the user can tag them or remove them.
I figured out how to upload the files and save them once the files are uploaded. I am keeping tracking of a global path where images are kept. In the database I keep the meta data about the images like file name, tags, etc.
I am using Java/JSP (specifically Stripes framework but my problem is generic).
My question is where do I keep these image files once they are uploaded?
Right now I have two web applications deployed on a Tomcat server. One main web application and other one is the where I upload the images.
But this does not work as I can not see the uploaded images in the main application until I redeploy/restart Tomcat.
It seems like Tomcat does not pick newly uploaded images automatically.
Does anyone have any solutions?
This is a simple project, so I do not want to store them in a database or use Apache for images. That is all just too complicated for this small project.
Thanks.
Definitely don't store the images in the database, but you will want to store the image path in the database. This will allow you to store the image just about anywhere.
Since you are using two tomcat applications, your best bet may be to store the images outside of either app and stream the image back to the user instead of letting tomcat manage the files. Otherwise, I would ask why you are trying to do this with two web apps.
However, storing uploaded images inside the web-app directory is not a wise thing to do, and you know it.
By the way, you might want to look this stackoverflow thread, lately discussed where to store the images. It might not solve your issue, surely will give you more confidence on what you are doing.
I've solved this in different ways.
First, the non-portable way, is that Glassfish (and I do believe Tomcat as well) allows you to map an external directory in to the webapps hierarchy. This works really well and does exactly what you want. It lets you store your images in an external directory away from your webapp, yet still serve them up.
However, this technique is not portable.
The way to I've done it portably is by creating a filter.
You place the filter someplace obvious, say "/images".
What the filter does is this:
it checks for the image (or anything, it works with any static resource) in a special directory within the webapp. For our example we'll use the url "/webapp/images".
if the file DOES NOT exist, we copy the file from your external location in to the appropriate spot within the webapp. So, let's say the reqyest url is "/images/banner.gif". And that your files are stored on disk at "/home/app/images". So, our source file is "/home/app/images/banner.gif". We then copy it to where we want it in the webapp tree. We use "ServletContext.getRealPath" for this. So, the destination will be "ServletContext.get RealPath("/webapp/images/banner.gif"). Just copy the source to the destination.
if the file already existed, or now exists, simply forward to the actual image at /webapp/images/banner.gif.
Effectively you end up having a file cache within your webapps deployment tree. The down side is that it's a cache, so it needs to be maintained (i.e. you should check if the original is newer than your cache, make sure you delete if the source is deleted, etc.). Also, it duplicates your resources, so your images will consume, eventually, twice as much disk space. Finally, there's the initial copy cost at start up.
However, it DOES work, and it prevents you from having to serve up static resources using your own code. (Which is the 3rd solution, map a filter/servlet to intercept the URLs and simply stream it your self.)
I would look at the construct within Tomcat (assuming it exists) to do the mapping for you. I know it exists in Glassfish. (Google alternatedocroot for Glassfish to see how it works.)
I was using two web applications to avoid over writing the uploaded images in case I redeploy a new main application war file.
But as you mention there is no other option but to stream them through a Servlet or something I guess I can keep them outside tomcat directory.
I wanted to avoid writing this Streaming Servlet. Just too small project to deal with all the mess (like proper content type, 404, etc.) while writing the streaming servlet.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Image streaming Servlet.
*/
public class ImageDisplayServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public ImageDisplayServlet() {
super();
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String relativePath = trimToEmpty(request.getPathInfo());
// Make sure no one try to screw with us.
// This is important as user can literally access any file if we are not careful
if(isXSSAttack(relativePath) == false) {
String pathToFile = this.getServletContext().getRealPath(request.getPathInfo());
File file = new File(pathToFile);
System.out.println("Looking for file " + file.getAbsolutePath());
// show a 404 page
if(!file.exists() || !file.isFile()) {
httpError(404, response);
} else {
try {
streamImageFile(file, response);
} catch(Exception e) {
// Tell the user there was some internal server error.\
// 500 - Internal server error.
httpError(500, response);
e.printStackTrace();
}
}
} else {
// what to do if i think it is a XSS attack ?!?
}
}
private void streamImageFile(File file, HttpServletResponse response) {
// find the right MIME type and set it as content type
response.setContentType(getContentType(file));
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
response.setContentLength((int) file.length());
// Use Buffered Stream for reading/writing.
bis = new BufferedInputStream(new FileInputStream(file));
bos = new BufferedOutputStream(response.getOutputStream());
byte[] buff = new byte[(int) file.length()];
int bytesRead;
// Simple read/write loop.
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
// To late to do anything about it now, we may have already sent some data to user.
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
// To late to do anything about it now, we may have already sent some data to user.
}
}
}
}
private String getContentType(File file) {
if(file.getName().length() > 0) {
String[] parts = file.getName().split("\\.");
if(parts.length > 0) {
// only last part interests me
String extention = parts[parts.length - 1];
if(extention.equalsIgnoreCase("jpg")) {
return "image/jpg";
} else if(extention.equalsIgnoreCase("gif")) {
return "image/gif";
} else if(extention.equalsIgnoreCase("png")) {
return "image/png";
}
}
}
throw new RuntimeException("Can not find content type for the file " + file.getAbsolutePath());
}
private String trimToEmpty(String pathInfo) {
if(pathInfo == null) {
return "";
} else {
return pathInfo.trim();
}
}
private void httpError(int statusCode, HttpServletResponse response) {
try {
response.setStatus(statusCode);
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
writer.append("<html><body><h1>Error Code: " + statusCode + "</h1><body></html>");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean isXSSAttack(String path) {
boolean xss = false;
// Split on the bases of know file separator
String[] parts = path.split("/|\\\\");
// Now verify that no part contains anything harmful
for(String part : parts) {
// No double dots ..
// No colons :
// No semicolons ;
if(part.trim().contains("..") || part.trim().contains(":") || part.trim().contains(";")) {
// Fire in the hole!
xss = true;
break;
}
}
return xss;
}
/**
* #see HttpServlet#doPost(Ht/promotions/some.jpgtpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
Ok Here is a Servlet that I quickly wrote that can stream images:
Here is the List of limitations and know issues:
May have XSS vulnerability use with care
Not production ready use as reference
Images need to in the web application directory. Can be easily change but I too lazy (it is not worth it the project is too small)
Only stream jpg,gif or png files.
Usage:
Let say you deploy this web application called images as separate application.
http://www.example.com/images/promotions/promo.jpg
means there should be a directory in "promotions" with image "promo.jpg" with in this images web application.
PS: Do not ask why I am doing this Servlet Container only solution that sucks big time.
<servlet>
<description></description>
<display-name>ImageDisplayServlet</display-name>
<servlet-name>ImageDisplayServlet</servlet-name>
<servlet-class>com.example.images.ImageDisplayServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImageDisplayServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Oh ya configure your Servlet like above for best results :P

Categories

Resources