Skip to Content

In the previous blog “Access BRM decision table from PI message mapping“, I explained how to use BRM decision tables to store value mappings and access them directly from PI message mappings. Today I am going to discuss further on how to read multiple rows from a decision table, store them locally in UDFs, and use them in message mappings. This helps to increase the performance by avoiding frequent BRM calls. Because each request to the BRM is logged into business log, which could hinder the overall system performance if called too often.

The example I use here for demo is to convert country codes to country names. I will however not repeat the same steps if they are already mentioned in the previous blog.

1. Create “value/mapping/ejb”, add Java class “ValueMapping” and declare public part

The Java Class looks like below.

import java.io.Serializable;
import java.util.ArrayList;

public class ValueMapping implements Serializable{
	private static final long serialVersionUID = 1L;
	private int index;
	private ArrayList<String> tCodes;
	private ArrayList<String> tNames;

	public ValueMapping() {
		super();
		this.tCodes = new ArrayList<String>();
		this.tNames = new ArrayList<String>();
	}

	public int getIndex() {
		return index;
	}

	public void setIndex(int index) {
		this.index = index;
	}

	public ArrayList<String> gettCodes() {
		return tCodes;
	}

	public void settCodes(ArrayList<String> tCodes) {
		this.tCodes = tCodes;
	}

	public ArrayList<String> gettNames() {
		return tNames;
	}

	public void settNames(ArrayList<String> tNames) {
		this.tNames = tNames;
	}

	public void addtCode(String tCode) {
		this.tCodes.add(tCode);
	}

	public void addtName(String tName) {
		this.tNames.add(tName);
	}
}

 

2. Creating “value/mapping/brm”, add dependency and create the BRM application

Below is how the BRM rule and decision table looks like:

3. Add dependency for “value/mapping/ejb”, and create a Java Session bean for accessing the BRM application

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;
import javax.naming.InitialContext;

import com.sap.brms.qrules.ejb.local.RuleEngineLocal;
import com.sap.brms.qrules.ejb.local.RuleEngineLocalHome;
import com.sap.brms.qrules.engine.RuleEngine;
import com.sap.brms.qrules.engine.RulesetContext;

/**
 * Session Bean implementation class ValueMappingFactory
 */
@Stateless
public class ValueMappingFactory implements ValueMappingFactoryRemote, ValueMappingFactoryLocal {
    public ValueMappingFactory() {
    }

	@SuppressWarnings("unchecked")
	@Override
	public ValueMapping convert(int index) throws Exception {
		List<ValueMapping> vmList = new ArrayList<ValueMapping>();
		ValueMapping in = new ValueMapping();
		ValueMapping out = new ValueMapping();
    	
    	in.setIndex(index);
    	vmList.add(in);
    	
    	InitialContext ic = new InitialContext();
		RuleEngineLocalHome home = (RuleEngineLocalHome) ic.lookup(RuleEngineLocalHome.JNDI_NAME);
	
		RuleEngineLocal local = home.create();
		RuleEngine engine = (RuleEngine) local;
		
		RulesetContext rsContext = engine.createRulesetContext("<your brm ruleset Guid>");
			
		rsContext.add(in);
		RulesetContext rntContext = engine.invokeRuleset(rsContext);
		vmList = rntContext.getReturnedFacts();
		
		if(vmList.size() == 0) {
			// Empty result found;
		} else {
			out = vmList.get(0);
		} 
		
		return out;
	}
}

4. Creating “value/mapping/ear”, add dependency and deploy applications into SAP PI run-time

Same as in the previous blog.

5. Create an UDF library “ValueMappingUDF” in ESR

init method:

public void init(GlobalContainer container) throws StreamTransformationException{
		String lookUp = "ejb:/interfaceName=<your ejb name>"; 

		try {
			InitialContext ic = new InitialContext();
			this.myObject= ic.lookup(lookUp);
			this.myClass = this.myObject.getClass();

			if (myClass != null) {
						 Class[] params = new Class[] {int.class};
							this.convert  = this.myClass.getDeclaredMethod("convert", params);
						
							Object[] inputs = new Object[] {10};
							Object vmObject = this.convert.invoke(this.myObject, inputs); 
								
							Class<?> vmClass = vmObject.getClass();
							Class[] vmParam = new Class[] {};
							Method vmGettCodes = vmClass.getDeclaredMethod("gettCodes");
							Method vmGettNames = vmClass.getDeclaredMethod("gettNames");
							
							ArrayList<String> tCodes = (ArrayList<String>) vmGettCodes.invoke(vmObject, vmParam);
							ArrayList<String> tNames = (ArrayList<String>) vmGettNames.invoke(vmObject, vmParam);
							
							// Go through array lists				
							for (int i = 0; i < tCodes.size(); i++) { 
									container.getTrace().addInfo("Key: " + tCodes.get(i) + "; Value: " + tNames.get(i));
									this.trMap.put(tCodes.get(i), tNames.get(i));
							}
			}
		} catch (Exception e) {
			throw new StreamTransformationException(e.getMessage());
		}
	}

convert method

public String convert(String input, Container container) throws StreamTransformationException{
	String rnt = this.trMap.get(input);

	if(rnt == null) {
		rnt = "DEFAULT";
	}

	return rnt;
}

 

there you go. Then you can use the UDF to access records in the BRM table. 🙂

To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

Leave a Reply