I have been following the Google Guestbook tutorial for AppEngine, and successfully completed the tutorial. I then went on to add my own part (uploading an image to the datastore) just for a challenge, but have run into a problem. My code compiles and deploys fine, but upon submitting a .jpg to the following form,
<form action="/image" method="post" enctype="multipart/form-data">
<div><input type="text" name="imageName"></input></div>
<div><input type="file" name="image" accept="image/*"></input></div>
<div><input type="submit" value="Post Image"/></div>
</form>
I receive the following error
java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.getPart(Ljava/lang/String;)Ljavax/servlet/http/Part;
at com.example.guestbook.ImageServlet.doPost(ImageServlet.java:49)
...
My servlet dependency in my pom is as follows:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
web.xml:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>sign</servlet-name>
<servlet-class>com.example.guestbook.SignGuestbookServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>image</servlet-name>
<servlet-class>com.example.guestbook.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sign</servlet-name>
<url-pattern>/sign</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>image</servlet-name>
<url-pattern>/image</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>guestbook.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>ObjectifyFilter</filter-name>
<filter-class>com.googlecode.objectify.ObjectifyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ObjectifyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>com.example.guestbook.OfyHelper</listener-class>
</listener>
</web-app>
and the servlet code that services the request is:
@MultipartConfig
public class ImageServlet extends HttpServlet {
// Process the http POST of the form
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser(); // Find out who the user is.
String imageName = req.getParameter("imageName");
try
{
Part part = req.getPart("image");
InputStream is = part.getInputStream();
byte[] bytes = null;
is.read(bytes);
Blob image = new Blob(bytes);
Image newImage = new Image(imageName, image);
// Use Objectify to save the greeting and now() is used to make the call synchronously as we
// will immediately get a new page using redirect and we want the data to be present.
ObjectifyService.ofy().save().entity(newImage).now();
}
catch(ServletException e)
{
e.printStackTrace();
}
resp.sendRedirect("/guestbook.jsp");
}
}
with the "Image" model being:
@Entity
public class Image {
@Id public Long id;
public String imageName;
public Blob image;
/**
* Simple constructor
**/
public Image() {
}
/**
* Takes all important fields
**/
public Image(String name, Blob newImage) {
imageName = name;
image = newImage;
}
}
I originally had a problem where the servlet version provided by the tutorial pom didn't support "getPart()" (2.7 I believe), but I updated it to 3.1 and am still greeted with the NoSuchMethodError. I guess there's a chance there could still be some artefact lying around which is still using the outdated servlet version, but personally I'm quite stumped.