GWT 2.1 – Uploading a file using the RPC mechanism

Share

Uploading a file in a project using GWT/EXT-GWT can be done in 2 ways : creating a separate servlet or using a library like the one presented here. Normally, because of browser security restrictions you can’t upload a file using RPC. But normally doesn’t mean never. This article will show you how to upload files using RPC in GWT projects.

Every now and then you might encounter a situation where you need to upload a file, but it would be very convenient to be able to use a RPC(Remote Procedure Call) to do that because you would like to perform some additional operations with that file.Well not to worry, this article will show you a way to do that.

We are going to start with the RPC implementation. First of all, we need to declare the RPC interfaces, this is no different from implementing an usual RPC. We are going to name our RPC “FileService”, and bellow you have the declaration of both interfaces

1. The FileService interface

@RemoteServiceRelativePath("GWTWebCbr3")
public interface FileService extends RemoteService {
 
	/**
	 * Method that stores a file on the server. It computes the save path
	 * depending on the case type and the case id.
	 */
	public String uploadAttachement(String caseId, String fieldName,boolean isNewCase);
 
	/**
	 * Method that deletes a file from the server. It computes the file path
	 * depending on the case type and the case id.
	 */
	public boolean deleteAttachement(String filePath, int caseID,
			String fieldName);
 
	/**
	 * Update the name of the attachment
	 */
	public String updateFileName(final String name);
}

2. The FileServiceAsync interface

public interface FileServiceAsync {
 
	/**
	 * Method that stores a file on the server. It computes the save path
	 * depending on the case type and the case id.
	 */
	void uploadAttachement(String caseId, String id, boolean isNewCase,
			AsyncCallback callback);
 
	/**
	 * Method that deletes a file from the server. It computes the file path
	 * depending on the case type and the case id.
	 */
	void deleteAttachement(String filePath, int id, String id2,
			AsyncCallback callback);
 
	/**
	 * Update the name of the attachment
	 */
	void updateFileName(String name, AsyncCallback callback);
 
}

So far there is nothing different, but the service implementation will reveal what makes uploading a file with RPC possible. Bassically you need to overwrite the          service(final HttpServletRequest request,HttpServletResponse response) method and that’s it.

Here’s the code for FileServiceImpl

public class FileServiceImpl extends RemoteServiceServlet implements
		FileService {
 
//code omitted
 
    private FileItem uploadedFileItem;
 
    @Override
    protected void service(final HttpServletRequest request,
	HttpServletResponse response) throws ServletException, IOException {
 
	boolean isMultiPart = ServletFileUpload
			.isMultipartContent(new ServletRequestContext(request));
 
	if(isMultiPart) {
		FileItemFactory factory = new DiskFileItemFactory();
		ServletFileUpload upload = new ServletFileUpload(factory);
 
		try {
			@SuppressWarnings("unchecked")
			List items = upload.parseRequest(request);
			uploadedFileItem = items.get(0); // we only upload one file
 
			if(uploadedFileItem == null) {
				super.service(request, response);
				return;
			} else if(uploadedFileItem.getFieldName().equalsIgnoreCase(
					"uploadFormElement")) {
				fileName = uploadedFileItem.getName();
				response.setStatus(HttpServletResponse.SC_CREATED);
				response.getWriter().print("OK");
				response.flushBuffer();
			}
 
		} catch(FileUploadException e) {
			LOG.error(e);
		}
	}
 
	else {
		super.service(request, response);
		return;
	}
    }
 
//code omitted
}

After you implement your service, you need to register it and you do that by adding the following lines to the web.xml file.

<servlet>
    <servlet-name>FileService</servlet-name>
    <servlet-class>ro.ropardo.cbr.server.Services.FileServiceImpl</servlet-class>
</servlet>
 
<servlet-mapping>
    <servlet-name>FileService</servlet-name>
    <url-pattern>/gwtwebcbr/GWTWebCbr3</url-pattern>
</servlet-mapping>

On the client side you need to use a FormPanel to upload your file. To tie the components together you need to set the action of the FormPanel to the RPC servlet. Here is an example :

private final FormPanel formPanel;
formPanel = new FormPanel();
formPanel.setAction(GWT.getModuleBaseURL()+”GWTWebCbr3”);
formPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
formPanel.setMethod(FormPanel.METHOD_POST);

Now all you have to do is submit the form. For example you can submit the form when a user clicks a button :

Button uploadButton = new Button(PARAM_BUTTON_UPLOAD);
uploadButton.addClickHandler(new ClickHandler() {
 
    @Override
    public void onClick(final ClickEvent event) {
	if(!uploader.getFilename().equalsIgnoreCase(PARAM_EMPTY_STRING)) {
	    formPanel.submit();
	}
 
    }
});

You can also add a handler to the form and do some action when the submit completed. For example, I trigger an event if the submit completed and the file was succesfully uploaded. To check if the upload was successful you need to write the status of the operation in the result object from the overriden service() method and then, from the client side, check that status. Here is an example :

formPanel
.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
 
    @Override
    public void onSubmitComplete(final SubmitCompleteEvent event) {
	// call upload method from service with the file's name
	String result = event.getResults();
	if(result.contains(PARAM_OK_STRING)) {
	    String name = uploader.getFilename();
 
	    // trigger some event that custom file editor will
	     FileReadyForUploadEvent ev = new FileReadyForUploadEvent(name);
	    fireEvent(ev);
 
	 }
    }
});

And that is how you can upload a file using the RPC mechanism in GWT based projects. I hope you can find this article usefull.

Finally, there’s another very important peculiarity of what does Cialis that brings it so high above its alternatives. It is the only med that is available in two versions – one intended for use on as-needed basis and one intended for daily use. As you might know, Viagra and Levitra only come in the latter of these two forms and should be consumed shortly before expected sexual activity to ensure best effect. Daily Cialis, in its turn, contains low doses of Tadalafil, which allows to build its concentration up in your system gradually over time and maintain it on acceptable levels, which, consequently, makes it possible for you to enjoy sex at any moment without having to time it.

13 thoughts on “GWT 2.1 – Uploading a file using the RPC mechanism”
  • Jeff MAURY says:

    Is the code available ?

    August 18, 2011 at 5:00 pm
  • Jorge says:

    Excellent article, came in very useful, cheers!

    October 5, 2011 at 4:34 pm
  • Fredrik says:

    Great article! Is there any special reason why we shouldn’t do this for all uploading?

    October 26, 2011 at 10:11 pm
  • rkd80 says:

    What is uploader?

    In the case of: uploader.getFilename();

    Is that the GWT fileuploader or something else??

    November 16, 2011 at 10:39 pm
  • Sergio says:

    It does not work, I get the following error:

    Exception while dispatching incoming RPC call
    javax.servlet.ServletException: Content-Type was ‘multipart / form-data; boundary =————————— 28945529321871’. Expected ‘text / x-gwt-rpc’.

    Is there source code?

    December 13, 2011 at 2:06 pm
  • Stelian Morariu says:

    Sorry for the late reply :
    @ rkd80 yes, that is the GWT fileuploader;
    @ Sergio as far as I can tell from your message, your error is related to the content-type you send, have you tried different settings for

    formPanel.setEncoding(FormPanel.ENCODING_MULTIPART);

    ?

    December 20, 2011 at 1:58 pm
  • Artiom says:

    Hello. Thx for useful post.
    Do you have an example how to use gwtupload with progressbar?

    Best regards/

    January 28, 2012 at 11:23 am
  • ze_felipe says:

    hi, i´m brazilian and my english is so so.

    Then, woks fine for me, but the problem is when i call this service, it

    redirect to http:// … / ‘myapplication’ / services and i cant back to

    my apllication. can you help me?

    tks

    February 9, 2012 at 7:46 pm
  • Mariah says:

    Hello thanks 4 da example… but i have a doubt…. the class FileServiceImpl send me an error and say that the method service cannot be override… what im doing wrong? thanks a lot

    May 25, 2012 at 7:32 pm
  • This is NOT “uploading using GWT-RPC”, it’s just using the same servlet for GWT-RPC and “something else” (in this case, file upload, but ti could really be anything).

    May 27, 2012 at 12:41 am
  • Stelian Morariu says:

    @Mariah – some details about that error ?

    @Thomas Broyer – what else do you understand by “uploading using GWT-RPC” other than using GWT’s RPC servlet for uploading files ?

    Thx for reading and posting.

    May 28, 2012 at 9:58 am
  • Pratz says:

    hi i want to do the same. In my case i have to send the file and their properties to server . For sending a file i used FormPanel and for properties i used RPC .

    public void onModuleLoad() {
    // TODO Auto-generated method stub
    final FileServiceEndPoint serviceEndPoint = new FileServiceEndPoint();
    new AddDocument();

    Button b = new Button(“add Properties”);
    b.addClickHandler(new ClickHandler() {

    private Map docProperty;

    public void onClick(ClickEvent event) {
    // TODO Auto-generated method stub
    docProperty =getProperties();
    AsyncCallback callback = new AsyncCallback() {
    public void onSuccess(String result) {
    System.out.println(“he ha” +result);
    }
    public void onFailure(Throwable caught) {
    }
    };
    serviceEndPoint.uploadAttachement(docProperty, callback);
    }
    });
    RootPanel.get().add(b);
    }
    }

    this new AddDocument(); contains code for uploading a file (formPanel code)
    Interface and async is same Like yours insted of Stings i passed HasMap.

    public class FileServiceEndPoint implements FileServiceAsync{

    FileServiceAsync service = (FileServiceAsync)GWT.create(FileService.class);
    ServiceDefTarget endpoint = (ServiceDefTarget) service;

    public FileServiceEndPoint() {
    endpoint.setServiceEntryPoint(GWT.getHostPageBaseURL() + “TestUploadFileServlet”);
    }

    public void uploadAttachement(Map docProperty,
    AsyncCallback callback) {
    service.uploadAttachement(docProperty, callback);
    }
    }

    On Server:

    public class FileUploadImpl extends RemoteServiceServlet implements FileService {

    private static final long serialVersionUID = 1L;
    private static final Logger log = Logger.getLogger(FileUploadImpl.class
    .getName());

    String a;
    protected void service(final HttpServletRequest request,HttpServletResponse response)
    throws ServletException,IOException {

    a=”5″;
    System.out.println(“ServletWorking Fine “);
    }
    public String uploadAttachement(Map docProperty) {
    // TODO Auto-generated method stub
    return “Checked”;
    }
    }

    When I debug formPanel.submit : the debugger goes in Server and print ServletWorking Fine(this is perfect)

    and when i debug the addProperties button it goes to server and print ServletWorking Fine. but It should not go in service method.
    the debugger should go in UploadAttachement.

    Plz tell how to pass hashMap using same servlet.

    August 24, 2012 at 11:57 am
  • Laurent says:

    Don’t forget that servlets are singleton.
    This code will have reentrancy problems because of FileItem attribute on servlet.

    you might use httpSession or private Map using a private transaction key.

    October 25, 2012 at 3:30 pm

Comments are closed.

By continuing to use the site, you agree to the use of cookies. More information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close