How to write content handlers for IS

Hello folks,

I am trying to write a content handler for MS Excel files that I want to upload to IS using a HTML form and then process in wM. I would appreciate if someone could help me by sample code etc. I am not very good in java but can manage it fairly well. So I would need some explaination and detail steps.

Thanks
Kazi

Kazi,

There is an example in the WmSamples package (available from Advantage only after IS 6.5). You might also find that a search on “ContentHandler” will turn up some informative posts such as this one.

Mark

Kazi

In the case of uploading files by user action form web page you probably be using some Tomcat servlet or perhaps POST HTML form and read file stream from client system. The content handler may not be the best solution. Typically content handler used in B2B transaction process sent direct from external clients like App server to WM IS over some protocol like HTTP/HTTP/FTP/SMTP.

Kazi in order to upload excel file you can use simple HTML form that selects file locally and submit HTML form data to your service. In turn the service will have input parameter type (Object) contentStream wich you can read using WM standard service for mime types basic HTTP protocol type operation to turn MIME data into meaningful headers and data stream. Then you can red it in Java as InputStream and write to file. With excel stored localy to IS you can read it with Excel service to convert and map it. No content handler is involved in this process.

But since you started this dicussion on content handlers here is how you would write one if you choose to:
Here is couple of steps to remember in case of your Excel file.

Important to keep in mind that when you use Apache POI to read Excel files the entire file must be read into memeory by POI in order to render the data. Unlike flat file or CVS you cannot read just part of file and get only part of data. This limits to some degree how large a file you can process to your memory resources in IS. Fortunately not many MS Excel are very large.

You can pick any content type name for your handler but I would recomend to use something meaningful like: “application/vnd.ms-excel” wich is vendor specific content - MS Excel.

To register handler you can write 2 Java services:
// Register content handler
ServerAPI.registerContentHandler(“application/vnd.ms-excel”, new ContentHandlerFactory_ExcelFile());

The Handler factory class [ContentHandlerFactory_ExcelFile] I will explain later on.

To unregister handler you can write Java service using simple code like this:

ServerAPI.removeContentHandler(“application/vnd.ms-excel”);

The handler Factory and handler classes you have to write outside WM Developer using JDK or your favorite IDE and use is calsses in package or package it into jar file. Here is ContentHandlerFactory_ExcelFile.java:

package com.wm.excel.net;

import com.wm.app.b2b.server.ContentHandler;
import com.wm.app.b2b.server.ContentHandlerFactory;

public class ContentHandlerFactory_ExcelFile extends ContentHandlerFactory
{
public ContentHandlerFactory_ExcelFile()
{
contentType = “application/vnd.ms-excel”;
}

public ContentHandlerFactory_ExcelFile(String contenttype)
{
    contentType = contenttype;
}

public ContentHandler create()
{
    return new ContentHandler_ExcelFile(contentType);
}

private String contentType;

}

Now what is left to write actual handler class, in this case ContentHandler_ExcelFile to actually handle your Excel data. I will try to show example in next posting.

Kazi

Here is the codefor Contente andler class discussed in previous posting. This class passes InoputStream directly to target service adn sevice can read the file streamfrom HTTP POST request to handle Excel file. I chose [exceldata] to be the stream input name of my service and handler uses same name to pass data over pipeline.

package com.wm.excel.content;

import com.wm.app.b2b.server.;
import com.wm.data.
;
import com.wm.util.Values;
import java.io.*;

public class ContentHandler_ExcelFile implements ContentHandler
{
private String contentType;
private static final String INPUT_KEY = “exceldata”;
private static final String OUTPUT_KEY = “excelreturn”;
private static final String STD_ENCODING = “UTF8”;
private static final String CONTENT_TYPE = “application/ms-excel”;
private static boolean returnStackTrace = Boolean.getBoolean(“ff.contenthandler.stacktrace”);

public ContentHandler_ExcelFile()
{
    contentType = CONTENT_TYPE;
}

public ContentHandler_ExcelFile(String contentType)
{
    this.contentType = contentType;
}

public String getContentType()
{
    return contentType;
}

public Values getInputValues(InputStream is, InvokeState state)
    throws IOException
{
    IData data = IDataFactory.create();
    if(state.getProtocolInfoIf() == null)
        return Values.use(data);
    Object o = state.getProtocolInfoIf().getProtocolProperty("transport");
    if(!(o instanceof IData))
    {
        return Values.use(data);
    } 
    else
    {
        IData pipeline = IDataFactory.create();
        ValuesEmulator.put(pipeline, INPUT_KEY, is);
        ValuesEmulator.put(pipeline, "fileName", "filename");
        ValuesEmulator.put(pipeline, "Content-type", contentType);
        return Values.use(pipeline);
    }
}

public void putOutputValues(OutputStream os, Values out, InvokeState state)
    throws IOException
{
    Object indata = out.get(INPUT_KEY);
    if(indata != null && (indata instanceof InputStream))
        out.remove(INPUT_KEY);
    int READ_BUFFER_SIZE = 40000;
    Object outdata = out.get(OUTPUT_KEY);
    if(outdata != null)
    {
        if(outdata instanceof InputStream)
        {
            BufferedInputStream bis = new BufferedInputStream((InputStream)outdata, READ_BUFFER_SIZE);
            BufferedOutputStream bos = new BufferedOutputStream(os, READ_BUFFER_SIZE);
            byte data[] = new byte[READ_BUFFER_SIZE];
            do
            {
                int bytesRead = bis.read(data, 0, READ_BUFFER_SIZE);
                if(bytesRead < 0)
                    break;
                bos.write(data, 0, bytesRead);
            } while(true);
            bos.flush();
        } 
        else
        {
        	if(outdata instanceof byte[])
        		os.write((byte[])outdata);
        }
    }
    Values errRec = (Values)out.get("$errorInfo");
    if(errRec != null)
    {
        os.write("\n".getBytes(STD_ENCODING));
        if(returnStackTrace)
        {
            String trace = errRec.getNonEmptyString("$errorDump");
            os.write(trace.getBytes(STD_ENCODING));
        } 
        else
        {
            String type = errRec.getNonEmptyString("$errorType");
            if(type != null)
            {
                os.write(type.getBytes(STD_ENCODING));
                os.write(": ".getBytes(STD_ENCODING));
            }
            String err = errRec.getNonEmptyString("$localizedError");
            if(err == null)
                err = errRec.getNonEmptyString("$error");
            if(err != null)
                os.write(err.getBytes(STD_ENCODING));
        }
    }
    os.flush();
}

}