maandag 11 juni 2007

a reusable sap pool

Through SAP JCO we can gather SAP information within Java. I'll explain the basics here while I'm revealing a library piece by piece.

SAP Connection

First we need to connect to SAP. Therefore create a connectionpool
public SAPPool(){
    // create pool
    JCO.addClientPool(
    ((String) properties.get(SAP_POOL_NAME), // Alias for this pool
    Integer.parseInt((String) properties.get(SAP_NR_CONNECTIONS)),// nr of connections
    (String) properties.get(SAP_CLIENT), // SAP client
    (String) properties.get(SAP_USERID), // userid
    (String) properties.get(SAP_PASSWORD), // password
    (String) properties.get(SAP_LANGUAGE), // language
    (String) properties.get(SAP_HOST_NAME), // host name
    (String) properties.get(SAP_SYSTEM_NUMBER) // system number
    );
    //...

Next you create a repository
    //...
    // Create a new repository
    repository = JCO.createRepository((String) properties
        .get(SAP_REPOSITORY_NAME), ((String) properties
        .get(SAP_POOL_NAME));
} //end of ctor

To reference a function through your repository
public IFunctionTemplate getSAPFunction(String functionName){
    repository.getFunctionTemplate(functionName);
}

Also you can get the client
public JCO.Client getSAPClient(){
    JCO.getClient(poolName)
}

And very important is not to forget to release it again
public void releaseClient(){
    JCO.releaseClient(client)
}


Because It's so important not to forget releasing your resources again and because of some other default handling of calling SAP functions we'll use an abstract class. Read more about my interface vs abstract class post to understand why.

What are the defaults?

get function let's do this in the ctor which takes the functionName as an argument. Also we preserve some references towards the input, output and tables parameterLists (SAPPool references to class holding the previous posted code)
public BaseSAPFunction(String functionName){
    IFunctionTemplate ftemplate = SAPPool.getSAPFunction(functionName);
    function = new JCO.Function(ftemplate);
    input = function.getImportParameterList();
    output = function.getExportParameterList();
    tables = function.getTableParameterList();
}

set input next we need to set the input parameters. In the BaseClass I did so by having an abstract method handling this. In the actual implementation the input parameterlist can be referenced. The actual implementation will follow in calling a function.
public abstract void setInput();

execute function for actual execution of function first get a client on which you can invoke the execute function like this
public void executeFunction(){
    client = SAPPool.getSAPClient();
    client.execute(function);
}

handle results this will also be abstract here because this depends on the actual implementation. Here it returns an Object for compatibility with non 1.5 code. This implies that you'll need to cast it the right way. If you can ensure you'll have only 1.5 using this library then use generics. Again the actual implementation will follow in calling a function.
public abstract Object getData();

release client is done by executing
    SAPPool.releaseClient();


All together this wil be chained in the right order with some general execute function like the following
 public Object execute() {
  setInput(); //see implementation for details
  executeFunction();
  Object obj = getData(); //see implementation for details
  SAPPool.releaseClient();
  return obj;
 }


calling a function

Now for calling a specific function I extend the previous explained BaseSAPFunction. Then I only need to make a ctor calling the super ctor with functionName as argument and implement the 2 abstract methods (and maybe some helpers). Classes using this function invoke the execute() method and cast the Object. That's it.
public class SomeSAPFunctionCall extends BaseSAPFunction{

    public SomeSAPFunctionCall(){
        super("ZBAPI_SOME_FUNCTION");
    }

    public void setInput(){
        input.setValue("fieldValue", fieldName);
        //more here
    }

    public void getData(){
        SomeDTO dto = new SomeDTO();
        JCO.table table = tables.getTable("TABLE_NAME");
        if(table != null) {
            do{
                dto.setAString(table.getString("A_STRING"));
                dto.setAnInt(table.getInt("AN_INTEGER"));
                //more here
            } while(table.nextRow());
        }
        return dto;
    }
}


usage
SomeDTO dto = (SomeDTO)new SomeSAPFunctionCall().execute();


resources

Geen opmerkingen:

Een reactie plaatsen