javing
javing

Reputation: 12423

Questions about the correct way of using servlets

I want to create a servlet that will allow me to upload image files from the client to the server. I am helping myself with the tutorial i found at apache site: http://commons.apache.org/fileupload/using.html

On my way i am finding some complications and doubts:

Question 1

I would like my servlet to prepare an object with all the values from the request(included images as byte[]) and pass it to an @EJB that will insert all in the database. Is that possible? Could you give some pseudo code tips on how to improve my current servlet to do that?

@WebServlet(name="uploadServlet")
public class FileUpload extends HttpServlet {

    @EJB
    private DBAccessEJB ejb;

    private static final long serialVersionUID = -1062753489906645120L;

    // Will be triggered when a post method is sent by the user(Example: Form
    // submit)
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // Check if the request is multipart
        boolean isMultipart = ServletFileUpload.isMultipartContent(req);

           // Create the object that willBe passed to the EJB 
              Thing thing = new Thing();

        if (isMultipart) {
            // If it is multipart, save the items in a FileItemfactory
            FileItemFactory factory = new DiskFileItemFactory();
            // Create an upload handler
            ServletFileUpload upload = new ServletFileUpload(factory);
            try {
                // Get the files out of the request
                List items = upload.parseRequest(req);
                Iterator iterator = items.iterator();
                while (iterator.hasNext()) {
                    // Get each of the items inside the items list
                    FileItem item = (FileItem) iterator.next();
                    // If the item does not come from a field
                    if (!item.isFormField()) {
                       //transform the uploaded images to byte[]
                                       //setTheImageValues of the object
                    }
                                    else {
                                       //set the text values of the object
                                    }
                }
                          //Pass the prepared object to the EJB to be inserted in DB
                          ejb.save(thing)
            } catch (FileUploadException fue) {
                fue.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}

Question 2

I thought about passing the request to the servlet through the managaged bean, instead from the JSF page, but i don't really know how to do it. Could you give me some tips? I also don't know how to do it in the normal way, from the page,what do you think would be the best way? This is what i did so far regarding to the managed bean:

public void save() {

        FacesContext fc = FacesContext.getCurrentInstance();
        HttpServletRequest req = (HttpServletRequest)fc.getExternalContext().getRequest();

//What else do i need here to pass the request to the server?
}

This would be at the page inside a multipart form:

<h:commandButton value="Submit" action="myBackingBean.save"/>

Question 3

In my JSF page i have more or less 10 values almost all are Strings. I take them from the JSF and temporary store them in the JSF page. If the servlet could take all the values from the request, there would be no need for this attributes in the backing bean. Do you think is this approach a good thing to do? Will this be process transaction secure, or is there any risk?

Upvotes: 1

Views: 304

Answers (2)

oberger
oberger

Reputation: 1217

Question 1-

Absolutely you will need Unique Identifiers for your files, but that becomes less complicated if you do things like storing files in folders by date/username, etc...

Here is a basic workflow for your program that you could use, based on what you have shown so far:

Client computer -> FileUploadServlet (utilizing Apache Commons File Upload)

Once inside the FileUploadServlet:

a) Save the information from the request to a Database by way of your EJB including the file name, Mime Type, information, etc...

b) While still inside the servlet, upload the file to your server, or if you need to, use a commercial solution such as Amazon S3 or Google Storage (by way of a Java API such as JetS3t)

Afterwards, return any necessary information to the client.

Question 2 -

What is your reasoning for requesting throught the Bean, why not just make the Servlet the action instead, and collect the information from the request? I would not make the Bean's save method available on the JSF, as that sounds insecure and un-authenticated.

Question 3 -

Same as above, why store information, even if temporarily, when it is available elsewhere?

Upvotes: 0

Peter Tillemans
Peter Tillemans

Reputation: 35341

Doubt #1 :

It looks like you use the EJB here as a service layer containing a DAO annotated with EJB annotations to make it a session bean. I do not like this approach and you'll run into issues caused by the difference of the EJB world and the HTTP request world.

It is important to note that one of the biggest reasons to use EJB's is to manage transactions and transaction have to remain short, in the order of ms. This is for a number of reasons, like for example locks on the database. However when dealing with http requests with uploads, this is no longer valid.

From another perspective is that a service layer should represent an abstraction of the database model and should show what you can do with the model from a user perspective. The user does not want to save an image to the database, the user wants to add a portrait to his profile.

instead of

ejb.save(thing)

I prefer functions like

profileService.addPortrait(uid, byte[] image);

This explicitely states what it does, and also satisfies the requirement of short transactions. This means the profile entity is available for other requests which may come concurrently (like some status image, or inbox status, ...)

Doubt #2 :

When in Rome, do as the Romans do...

and start by learning some basics of the language. In this case learn JSF from some tutorials.

Doubt #3 :

Intercepting the request parameter in flight between the browser and the JSF component breaks the component architecture and the data hiding principle. It will also bypass any security measures and validation implemented in the server side parts of the JSF components.

If you use the JSF component framework, it makes sense to only ask the values from the components, not from the request itself.

From your 3 doubts I feel you have a bigger doubt : Should I be using JSF?

If it is mandated by your employer : suck it up, and start hitting the books... Learn which problems JSF and EJB's solve and frame your work in terms of those problems.

If you have the freedom to choose : choose a lighter framework, e.g. Spring + Spring MVC. You'll gain experience and encounter those problems at your own pace.

Upvotes: 1

Related Questions