HttpServletRequest does not return null? - java

I have a form:
<form action='?hasScenario=1' method='post' enctype='multipart/form-data'>
<input type='file' name='file'/>
<input type='submit' />
</form>
In tomcat 8.0 I want to do:
private void handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
Part filePart = request.getPart("file");
....
}
In documentation I see I should get null if user doesn't enter any value. I havn't (intentionally) configured anything special for multipart/file uploading in web.xml or server. But instead of null I get:
java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided
I would like to handle nicely cases, when some parameters are not provided, how to do that? Catching and doing nothing on IllegalStateException is not nice way for me - in case of no parameter I'd like to ask user for file instead of scaring him with 'error/warning' words.

It is a great way to find answer myself - just ask question to others :)
multipart-config in web.xml is a must. So my servlet part looks currently like:
<servlet>
<description>Scenario</description>
<servlet-name>Scenario</servlet-name>
<servlet-class>path-to-the-servlet</servlet-class>
<multipart-config>
<max-file-size>3145728</max-file-size>
<max-request-size>5242880</max-request-size>
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>Scenario</servlet-name>
<url-pattern>/scenario</url-pattern>
</servlet-mapping>
Before calling getPart it's important to check there are any data, like with:
if (request.getContentType() != null)
Part filePart = request.getPart("file");
...
And so finally filePart is null or a valid variable
Still I can't understand how have they made getParameter working in this post
How to upload files to server using JSP/Servlet? but this is different story :)

Related

Adding default servlet and forwarding to an HTML creates stackoverflowerror

I am using Jetty. My default servlet is making a simple forward to an HTML file in my WEB-INF folder that is causing a java.lang.StackOverFlowError error. The error is fixed if I rename the file I am forwarding from a .html to .jsp
DefaultServlet.java
public class DefaultServlet extends HttpServlet{
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
req.getRequestDispatcher("WEB-INF/home.html").forward(req, resp);
}
}
web.xml
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>Default</servlet-name>
<servlet-class>DefaultServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
My guess is that instead of inserting the html content in the response body, the forward is sending the browser a redirect to /WEB-INF/home.html. This again calls the DefaultServlet and gets into an infinity loop. How can I prevent this?
Thanks.
The "default servlet", which is mapped on a special URL pattern of /, is a very special servlet which is invoked when there's a request which does not match any of the servlets mapped on a more specific URL pattern such as *.jsp, /foo/*, etc.
When you forward to home.html, for which apparently no one servlet is registered, then the default servlet is invoked once again. However, the default servlet is ignorantly forwarding to the very same HTML file once again instead of actually serving the requested HTML file. It'll on the forward still find no one servlet matching the forward URL and it'll still invoke the default servlet once again. And again. Etc. When this is performed so many times that the stack cannot keep track anymore of all those in sequence invoked doGet() methods (usually around 1000), then you'll get a StackOverflowError.
That it works with a JSP file has actually a very simple reason: there's already a JspServlet registered on an URL pattern of *.jsp. So the badly designed default servlet isn't invoked.
Your default servlet should instead be obtaining the HTML file's contents via ServletContext#getResourceAsStream() and write it to the HttpServletResponse#getOutputStream().
However, it's also quite possible that you completely misunderstood the whole meaning of "default servlet" and/or the special meaning of the URL pattern / and actually merely want a servlet acting as home page. In that case, you should be mapping the servlet on a more specific URL pattern (and please rename the currently obviously quite confusing class name DefaultServlet to something else):
<servlet>
<servlet-name>home</servlet-name>
<servlet-class>com.example.HomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>home</servlet-name>
<url-pattern>/home</url-pattern>
</servlet-mapping>
And then register exactly that URL as welcome file:
<welcome-file-list>
<welcome-file>home</welcome-file>
</welcome-file-list>
You need kind of exclude urls ends with "html".
See for example this link explaining similar problem solution Can I exclude some concrete urls from <url-pattern> inside <filter-mapping>?

Incorrect content type for PDF file with Firefox

I am using Spring 3.2.0.M2 and I am trying to upload a pdf file.
JSP file :
<form method="POST" action="upload" enctype="multipart/form-data>
<input type="file" name="file" />
</form>
Controller :
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public String handleUpload(#RequestParam MultipartFile file) {
System.out.println(file.getContentType());
//prints "application/text-plain:formatted"
}
I am using the Standard multipart resolver :
<servlet>
<servlet-name>servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<multipart-config />
</servlet>
with :
<bean id="multipartResolver"
class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</bean>
I also tried with CommonsMultipartResolver from Apache but the problem is the same.
What I am getting is "application/text-plain:formatted" instead of "application/pdf".
I tested with several pdf file (from different sources). When I try to upload another file type (e.g. Word document), it works as expected (for a Word document, I get "application/msword").
I intend to store the content type (and the file name) into a database for later retrieval and download of the file. Having an incorrect content type is then causing an exception when calling setContentType like this :
public void downloadResource(#RequestParam("resId") Long resourceId, HttpServletResponse response) {
// get resource with its id.
response.setContentType(resource.getContentType());
//throws org.apache.tomcat.util.http.parser.TokenMgrError
}
The exception message is :
Lexical error at line 1, column 23. Encountered: ":" (58), after : ""
Had the same problem with a .svg file.
Solved it by modifying the Mozilla Firefox mimeTypes.rdf file in the profile folder. (thx to Piotrs Link above)
For other people having a similar problem. This was caused due to a mistakenly set Content-Type in my PHP script. When first testing the script (it delivered a svg file indirectly via php) i had another Content-Type set in the header().
header("Content-Type: image/svg+xml"); //should have been
header("Content-Type: application/vnd.android.package-archive"); //was actually set
This now overruled the content type setting in the firefox mimeTypes.rdf file:
<RDF:Description RDF:about="urn:mimetype:application/vnd.android.package-archive"
NC:value="application/vnd.android.package-archive"
NC:editable="true"
NC:fileExtensions="svg"
NC:description="Scalable Vector Graphics">
<NC:handlerProp RDF:resource="urn:mimetype:handler:application/vnd.android.package-archive"/>
</RDF:Description>
Probably because FF thinks its seeing a "new" file/filetype - and adding it to its config.
To fix this, you only need to delete the wrong XML section in the mimeTypes.rdf and restart FF of course.

Customize <url-pattern> to link a Form to a FormAction

First, I am a newbie in Java/J2EE development. So, please be indulgent with my leak of vocabulary (but feel free to correct me ;)
Here is my first problem :
I built a first form (named form1) in a .jsp page :
<form name="form1" action="formaction1.do" method="get">
I redirect the result of my form to a FormAction1 java class :
<servlet>
<servlet-class>com.servlet.myproject.FormAction1</servlet-class>
<servlet-name>FormAction1</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>FormAction1</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
Here is my FormAction1 java class :
public class FormAction1 extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
request.getRequestDispatcher("formaction1.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
doGet(request, response);
}
}
This is working fine.
Now, I'd like to create another form, named form2, and link it to FormAction2.
However, FormAction1 receives every .do request !
I tried to customize my <url-pattern> by writing :
<url-pattern>formaction1.do</url-pattern>
I guess it would've been too easy :D
Tomcat doesn't like it : I get a 404 error on every page of my project.
So, do you have any solution ?
Just a bonus question :
What's the point to use a class like FormAction1, rewrite doGet method, while I can just write :
<form name="form1" action="anotherFile.jsp" method="get">
and recover infos with a request.getParameter() in anotherFile.jsp ?
doesn't url-pattern requires a match starting from the beginning, in that case
<url-pattern>/formaction1.do</url-pattern>

how to call jsp file from java?

I have two jsp file and one java file. My constraints is if jspfile1 call java then java file call the jspfile2. Is it possible?
How to achieve this?
If by "Java file" you mean a Servlet, you can use the RequestDispatcher:
request.getRequestDispatcher("/my.jsp").include(request, response);
request.getRequestDispatcher("/my.jsp").forward(request, response);
The normal way is using a Servlet. Just extend HttpServlet and map it in web.xml with a certain url-pattern. Then just have the HTML links or forms in your JSP to point to an URL which matches the servlet's url-pattern.
E.g. page1.jsp:
<form action="servletUrl">
<input type"submit">
</form>
or
click here
The <form> without method attribute (which defaults to method="get") and the <a> links will call servlet's doGet() method.
public class MyServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Do your Java code thing here.
String message = "hello";
request.setAttribute("message", message); // Will be available in ${message}.
// And then forward the request to a JSP file.
request.getRequestDispatcher("page2.jsp").forward(request, response);
}
}
If you have a <form method="post">, you'll have to replace doGet by doPost method.
Map this servlet in web.xml as follows:
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>com.example.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myServlet</servlet-name>
<url-pattern>/servletUrl</url-pattern>
</servlet-mapping>
so that it's available by http://example.com/contextname/servletUrl. The <form> and <a> URL's have to point either relatively or absolutely to exact that URL to get the servlet invoked.
Now, this servlet example has set some "result" as request attribute with the name "message" and forwards the request to page2.jsp. To display the result in page2.jsp just do access ${message}:
<p>Servlet result was: ${message}</p>
Do a http web request.
jsp files get converted to a servlet. You cannot call them directly.
EDIT : typo fixed.

What is the best way to create a Java Servlet or JSP that optionally includes content depending on URL parameters

I want to create a JSP page or servlet that will work in 2 ways.
A user visits their own profile page:
http//something.com/profile/
Or they visit their friends page:
http://something.com/profile/FriendsName
They could also visit their own page through an explicit URL like:
http://something.com/profile/YourName
I have a servlet-mapping setup as follows to map any requests to /profile to my JSP that will handle that request.
<servlet>
<servlet-name>Profile</servlet-name>
<jsp-file>/profile.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>Profile</servlet-name>
<url-pattern>/profile</url-pattern>
</servlet-mapping>
Then I was thinking I could setup a filter that will parse the HTTPServletRequest's URL to read after the /profile/.
<filter>
<filter-name>profile-filter</filter-name>
<filter-class>ProfileFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>profile-filter</filter-name>
<url-pattern>/profile*</url-pattern>
</filter-mapping>
Now the filter could set attributes in the HttpServletRequest, how would i go about pulling those out in the JSP page to check if a user name was specified and check if your own name was set?
How would I go about creating a page scoped bean in the ServletFilter so I could use in the JSP page using jspBean like this:
<jsp:useBean id="profileInfo" scope="page" class="ProfileInfo" />
I think a filter only serves to artificially break the logic apart. You can very easily determine the value of the portion of the URL that doesn't match the url-pattern described in the web.xml. The HttpServletRequest class has a method that returns this value for you, it's called getPathInfo(). Here's an example:
<%
String path = request.getPathInfo();
if (path == null || "".equalsIgnoreCase(path)) {
// The path was empty, display the current user's profile
} else {
// Display the named profile
}
%>
This doesn't help you at all with the request beans, but I think it helps with the design.
I'm not completely following the question, but if you want a jsp to access request parameters or attributes, just do:
<%
String parameter = request.getParameter("parameter");
String attribute = request.getAttribute("attribute");
%>
You can also get access to the request url, etc... if you need to do anything with those.
Personally, I'd recommend that you use a servlet to handle your requests, and forward to the jsp of your choosing (possibly after setting session information that the jsp can use).
Using server level filters and request attributes for this kind of thing may be a bit overkill, but only you know your project's true requirements.

Categories

Resources