Thursday, August 23, 2018

Why do we need to model messages

IIB supplies a range of parsers to parse and write message formats. Some message formats are self-defining and can be parsed without reference to a model. However, most message formats are not self-defining, and a parser must have access to a predefined model that describes the message, if it is to parse the message correctly.
An example of a self-defining message format is XML. In XML, the message itself contains metadata in addition to data values, and it is this metadata that enables an XML parser to understand an XML message even if no model is available. Another example of a self-defining format is JSON.
Examples of messages that do not have a self-defining message format are CSV text messages, binary messages that originate from a COBOL program, and SWIFT formatted text messages. None of these message formats contain sufficient information to enable a parser to fully understand the message. In these cases, a model is required to describe them.
Even if your messages are self-defining, and do not require modeling, message modeling has the following advantages:
  • Runtime validation of messages. Without a message model, a parser cannot check whether input and output messages have the correct structure and data values.
  • Enhanced parsing of XML messages. Although XML is self-defining, all data values are treated as strings if a message model is not used. If a message model is used, the parser is provided with the data type of data values, and can cast the data accordingly.
  • Improved productivity when writing ESQL. When you are creating ESQL programs for IIB flows, the ESQL editor can use message models to provide code completion assistance.
  • Drag-and-drop operations on message maps. When you are creating message maps for IIB message flows, the Graphic Data Mapping editor uses the message model to populate its source and target views. Without message models, you cannot use the Graphical Data Mapping editor.
  • Reuse of message models, in whole or in part, by creating additional messages that are based on existing messages.
  • Generation of documentation.
  • Provision of version control and access control for message models by storing them in a central repository.
To make full use of the facilities that are offered by IIB, model your message formats.
To speed up the creation of message models, importers are provided to read metadata such as C header files, COBOL copybooks, and EIS metadata, and to create message models from that metadata. Additionally, predefined models are available for common industry standard message formats such as SWIFT, EDIFACT, X12, FIX, HL7, and TLOG.


XML Schema 1.0 (XSD) is an open standard modeling language from the World Wide Web Consortium (W3C) that was designed to model and validate XML documents. However, it can also be used to express the logical structure of all data formats. For more information about XML Schema, see XML Schema.
Data Format Description Language 1.0 (DFDL) is an open standard modeling language from the Open Grid Forum (OGF) that builds upon the features of XSD 1.0 in order to model and validate all kinds of general text and binary data. It uses standard XSD model objects to express the logical structure of the data, together with DFDL annotations to describe the text or binary physical representation. For more information about DFDL, see Data Format Description Language (DFDL).
WebSphere Adapter Schema is an IBM® extension to XSD 1.0. It uses the standard XSD model objects to express the logical structure of data, along with special annotations that are used when exchanging data with EIS systems that use the WebSphere Adapters of the broker.


A fragment of a DFDL schema that shows how delimited text data can be modeled.
Consider the following delimited ASCII text data:
int=5;float=-7.1E8copy to clipboard
In this data
  • int= and float= denote the start of an element. They are initiators.
  • The semicolon after 5 marks the boundary between the two elements in a sequence, and is a separator.
  • 5 is an integer in ASCII text.
  • -7.1E8 is a floating point number in ASCII text.
This is represented in a DFDL schema file as follows:
<xs:complexType name="myNumbers">
  <xs:sequence>

    <xs:annotation>
      <xs:appinfo source="http://www.ogf.org/dfdl/v1.0">
        <dfdl:sequence separator=";" encoding="ascii"/>
      </xs:appinfo>
    </xs:annotation>

    <xs:element name="myInt" type="xs:int">
      <xs:annotation>
        <xs:appinfo source="http://www.ogf.org/dfdl/v1.0">
          <dfdl:element representation="text"
                textNumberRep="standard" encoding="ascii"
                lengthKind="delimited" initiator="int=" …/>
        </xs:appinfo>
      </xs:annotation>
    </xs:element>

    <xs:element name="myFloat" type="xs:float">
      <xs:annotation>
        <xs:appinfo source="http://www.ogf.org/dfdl/v1.0">
          <dfdl:element representation="text"
                textNumberRep="standard" encoding="ascii"
                lengthKind="delimited" initiator="float=" …/>
        </xs:appinfo>
      </xs:annotation>
    </xs:element>

  </xs:sequence>
</xs:complexType>

Wednesday, July 11, 2018

JCN




The UserDefined configurable service is only accessible via a Java compute node. It cannot be accessed directly in ESQL. If you want to use ESQL, you need to create the code in Java and then use a function call to the Java code.
To set up the ESQL function call:
  1. CREATE PROCEDURE getUserDefinedConfigServProp( IN P1 CHARACTER )
  2. LANGUAGE JAVA
  3. EXTERNAL NAME "com.ibm.broker.test.MyClass.getUserDefinedConfigServProp";
To call this procuedure:
  1. DECLARE result CHARACTER getUserDefinedConfigServProp('test');
And the Java code could look something like this:
  1. public static String getUserDefinedConfigServProp(String cs){
  2. String rs = "exception occurred: ";
  3. try{
  4. BrokerProxy bp = BrokerProxy.getLocalInstance();
  5. short c = 0;
  6. while(!bp.hasBeenPopulatedByBroker()){
  7. try{
  8. c++; //loop count, in the rare case it fails, we need to leave the loop
  9. Thread.sleep(100);
  10. }catch(InterruptedException e){
  11. return rs+e.toString();
  12. }
  13. if(c > 4)
  14. return rs+"timed out";
  15. }
  16. try{
  17. ConfigurableService udcs = bp.getConfigurableService("UserDefined", cs);
  18. Properties props = udcs.getProperties();
  19. String out = "";
  20. for(String key : props.stringPropertyNames()){
  21. out = out+key+"="+props.getProperty(key)+",";
  22. }
  23. if(out.length > 0)
  24. rs=out.substring(0,out.length()-1);
  25. else
  26. rs=rs+"no properties returned"
  27. }catch(ConfigManagerProxyPropertyNotInitializedException e){
  28. return rs+e.toString();
  29. }
  30. }catch(ConfigManagerProxyLoggedException e){
  31. return rs+e.toString();
  32. }
  33. return rs;
  34. }


package bpmfacade.subflows;

import java.util.HashMap;
import java.util.Properties;

import com.ibm.broker.config.proxy.BrokerProxy;
import com.ibm.broker.config.proxy.ConfigManagerProxyLoggedException;
import com.ibm.broker.config.proxy.ConfigManagerProxyPropertyNotInitializedException;
import com.ibm.broker.config.proxy.ConfigurableService;
import com.ibm.broker.javacompute.MbJavaComputeNode;
import com.ibm.broker.plugin.MbElement;
import com.ibm.broker.plugin.MbException;
import com.ibm.broker.plugin.MbMessage;
import com.ibm.broker.plugin.MbMessageAssembly;
import com.ibm.broker.plugin.MbOutputTerminal;
import com.ibm.broker.plugin.MbUserException;

public class ReadConfiguration extends MbJavaComputeNode {

public  HashMap<String,String> getUserDefinedConfigServProp(String[] keys){
      String rs = "exception occurred: ";
      BrokerProxy bp =null;
      HashMap<String,String> properties = new HashMap<String,String>();
      boolean cacheExists =false;
      try{
      for (String key : keys) {
      if((rs = CacheManager.readFromCache("BPMConfigCache", key)) != null)
      {
      cacheExists = true;
      properties.put(key, rs);
      }
      }
      if(cacheExists == false)
      {
      // If it does not exist in the cache get it from config service
          bp = BrokerProxy.getLocalInstance();
          while(!bp.hasBeenPopulatedByBroker()) { Thread.sleep(100); }
      for (String key : keys) {
               // Check cache
      if((rs = CacheManager.readFromCache("BPMConfigCache", key)) != null)
      {
      properties.put(key, rs);
      }
      else
      {
           try{
                ConfigurableService udcs = bp.getConfigurableService("UserDefined",
                "BPMFacadeConfiguration");
                Properties props = udcs.getProperties();
                String out = "";
                out = props.getProperty(key);
                if(out == "")
                {
                     rs=rs + "no property returned";
                }
                else
                {
                rs = out;
                }
    // Insert into Cache
    CacheManager.insertIntoCache("BPMConfigCache", key, rs);
           }
           catch(ConfigManagerProxyPropertyNotInitializedException e){
                //return rs+e.toString();
           }
           properties.put(key, rs);
      }
    }
      }
      }
      catch(ConfigManagerProxyLoggedException e){
           //return rs+e.toString();
      } catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
      finally{
      if(bp != null)
      {
      bp.disconnect();
      }
      }
      return properties;
}


public void evaluate(MbMessageAssembly inAssembly) throws MbException {
MbOutputTerminal out = getOutputTerminal("out");
MbOutputTerminal alt = getOutputTerminal("alternate");

MbMessage inMessage = inAssembly.getMessage();
MbMessageAssembly outAssembly = null;
try {
// create new message as a copy of the input
MbMessage outMessage = new MbMessage(inMessage);
outAssembly = new MbMessageAssembly(inAssembly, outMessage);
// ----------------------------------------------------------
// Add user code below
String[] keys = {"Process_Server_URL", "User_Identity","User_Password", "Max_Users"};
HashMap<String,String> properties =  getUserDefinedConfigServProp(keys);

String process_Server_URL = properties.get("Process_Server_URL");
String user_Identity = properties.get("User_Identity");
String user_Password = properties.get("User_Password");
String max_Users = properties.get("Max_Users");



MbMessage env = inAssembly.getGlobalEnvironment();
MbMessage lenv = inAssembly.getLocalEnvironment();
//MbMessage newEnv = new MbMessage(env);

env.getRootElement().createElementAsFirstChild(
MbElement.TYPE_NAME_VALUE,
"Process_Server_URL",
process_Server_URL);
env.getRootElement().createElementAsFirstChild(
MbElement.TYPE_NAME_VALUE,
"User_Identity",
user_Identity);
env.getRootElement().createElementAsFirstChild(
MbElement.TYPE_NAME_VALUE,
"User_Password",
user_Password);
env.getRootElement().createElementAsFirstChild(
MbElement.TYPE_NAME_VALUE,
"Max_Users",
max_Users);

outAssembly = new MbMessageAssembly(
inAssembly,
lenv,
inAssembly.getExceptionList(),
inAssembly.getMessage());

// End of user code
// ----------------------------------------------------------
} catch (MbException e) {
// Re-throw to allow Broker handling of MbException
throw e;
} catch (RuntimeException e) {
// Re-throw to allow Broker handling of RuntimeException
throw e;
} catch (Exception e) {
// Consider replacing Exception with type(s) thrown by user code
// Example handling ensures all exceptions are re-thrown to be handled in the flow
throw new MbUserException(this, "evaluate()", "", "", e.toString(),
null);
}
// The following should only be changed
// if not propagating message to the 'out' terminal
out.propagate(outAssembly);

}

}

Distributed Computing: A Guide to Comparing Data Between Hive Tables Using Spark

In big data, efficient data comparison is essential for ensuring data integrity and validating data migrations. Apache Spark, with its in-me...