Saturday, July 25, 2015

[WSO2 AM] Invoke file upload spring service using WSO2 API Manager(1.9).

This is one use case I tried recently. So I thought to post that as a blog post :).

1. Deploy sample spring service to upload a file.

i  Download the sample service from this website https://spring.io/guides/gs/uploading-files/  (download link https://github.com/spring-guides/gs-uploading-files/archive/master.zip)

The FileUploadController.java class like bellow.

package hello;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class FileUploadController {
    
    @RequestMapping(value="/upload", method=RequestMethod.GET)
    public @ResponseBody String provideUploadInfo() {
        return "You can upload a file by posting to this same URL.";
    }
    
    @RequestMapping(value="/upload", method=RequestMethod.POST)
    public @ResponseBody String handleFileUpload(@RequestParam("name") String name, 
            @RequestParam("file") MultipartFile file){
        if (!file.isEmpty()) {
            try {
                byte[] bytes = file.getBytes();
                BufferedOutputStream stream = 
                        new BufferedOutputStream(new FileOutputStream(new File(name)));
                stream.write(bytes);
                stream.close();
                return "You successfully uploaded " + name + "!";
            } catch (Exception e) {
                return "You failed to upload " + name + " => " + e.getMessage();
            }
        } else {
            return "You failed to upload " + name + " because the file was empty.";
        }
    }

}
ii Unzip the file and go to the gs-uploading-files-master\complete directory from command window.

iii. Execute the following command to build the executable jar file.(You should have maven 3.x installed)

mvn  clean install

(The default pom file configured to build with Java 8 , if you are using  java 6 or 7 change the following section in the pom file gs-uploading-files-master\complete\pom.xml)
 <properties>
        <java .version="">1.7</java>
    </properties>


iv.  Go to the target directory and execute the following command to run our file upload service.

java -jar gs-uploading-files-0.1.0.jar


v. When you locate your browser to http://localhost:8080/ , you should be able to see the service UI to upload a file.

vi. You can send a POST request to http://localhost:8080/upload to upload file as well.

2. Create a API for this service using WSO2 API Manager.

i. Required fields to create an API.

API Name: FileUploadAPI
Context    : /fileupload
Version    : 1.0.0
URL pattern : /*
HTTP Method : POST
Production URL :  http://localhost:8080/upload
Tier Availability : Unlimited 
 
ii. After published API , log in to the store , subscribe to API and generate token.

iii) Generate SOAP UI project using the API endpoint https://localhost:8243/fileupload/1.0.0

  • Change the HTTP method to POST.
  • Add a query parameter "name". (because hanleFileUpload operation in FileUploadController.java expect that parameter).
  • Select the Media Type as "multipart/form-data" . (because we send file to the upload service as an attachment)
  • Add Authorization header.(because we invoke OAuth2 protected resource exposed by WSO2 API Manager)

iv) Add a file as attachment in SOAP UI.


v) Now when you send a request,  you should see the error message which similar to this.

{
   "timestamp": 1437841327984,
   "status": 400,
   "error": "Bad Request",
   "exception": "org.springframework.web.bind.MissingServletRequestParameterException",
   "message": "Required MultipartFile parameter 'file' is not present",
   "path": "/upload"
}



vi) To avoid this issue , you need to define the ContentID as "file", in the attachment window.


This ContentID value is depend on the name given for the RequestParam [eg: @RequestParam("file")] defined for the MultipartFile in method signature.
public @ResponseBody String handleFileUpload(@RequestParam("name") String name, 
            @RequestParam("file") MultipartFile file){


vii) Go to the place you execute the jar file, then you should see the uploaded file.


Friday, July 3, 2015

[WSO2 AM] Add "getRecentlyAddedAPIs" operation for Store API - WSO2 API Manager.

The WSO2 API Manager doesn't expose the "getRecentlyAddedAPIs" operation through the Store API (https://docs.wso2.com/display/AM190/Store+APIs). But you can do the following workaround to expose that operation.

1. Open the file <am_home>/repository/deployment/server/jaggeryapps/store/site/blocks/api/recently-added/ajax/list.jag and change it as bellow.

<%
include("/jagg/jagg.jag");
(function () {
    response.contentType = "application/json; charset=UTF-8";
    var mod, obj, tenant, result, limit,

            msg = require("/site/conf/ui-messages.jag"),
            action = request.getParameter("action");
    if (action == "getRecentlyAddedAPIs") {
        tenant = request.getParameter("tenant");
        limit = request.getParameter("limit");
        mod = jagg.module("api");
        result = mod.getRecentlyAddedAPIs(limit,tenant);
        if (result.error) {
            obj = {
                error:result.error,
                message:msg.error.authError(action)
            };
        } else {
            obj = {
                error:false,
                apis:result.apis
            }
        }
        print(obj);
    } else {
        print({
            error:true,
            message:msg.error.invalidAction(action)
        });
    }
}());
%>

2. Now you can invoke the getRecentlyAddedAPIs operation as bellow.

curl -b cookies 'http://localhost:9763/store/site/blocks/api/recently-added/ajax/list.jag?action=getRecentlyAddedAPIs&limit=10&tenant=carbon.super'

limit - Number of recently added APIs
tenant - Tenant domain.