Aug 17, 2017
Access APIs , When you don’t have MI Test
Jun 15, 2017
A New Beginning
Today we embarked a new journey. Brandix I3 became Fortude (http://fortude.co/) . I’m very proud that I WAS one of the first team at Brandix I3 & I’M now one of the first team at Fortude.
My Team & I, as M3 development team, supported to grow Brandix I3, working with almost all it’s customers. We are not going to stop. We are endeavouring as development HUB to grow Fortude exponentially. !
Dec 29, 2016
Browse Control for ISO SDK App–Part 1
Background
In a conventional M3 Program, data in some fields can be searched by pressing the F4 key or Browse function.
Using MAK (M3 Adaptation Kit – the framework to develop M3 programs), it is just mater of overriding PxPMT() to enable this Browse feature. However, in SDK development, we don’t have that option. Neither a function to override nor control to re-use.
Instead, using WPF & C# we have to create it from the scratch. I did this for my current SDK project and going to share with SDK development community.
There is an article in Potato IT blog (https://potatoit.kiwi/2013/09/19/smart-office-sdk-first-project-part-6-the-browse-control/). This was a good starting point for me. However, since I have MAK background, I wanted to implement similar way, that PxPMT() method does (below is an excerpt of M3 Browse )
if (IN62) { if (DSP.hasFocus("W1TOOL")) { this.PXFILE.moveLeft("CSYTAB00"); this.PXMBR.clear(); this.PXOPT = '1'; this.PXKVA1.moveLeft(LDAZD.CONO, 3); this.PXKTY1.move("EQ"); this.PXKTY2.move("EQ"); this.PXKVA3.moveLeft("TOOT"); this.PXKTY3.move("EQ"); this.PXKVA4.moveLeft(DSP.W2TOOT); this.PXFLD1.moveLeftPad("CTSTKY"); this.PXFLD2.moveLeftPad("CTTX15"); this.PXF11 = '1'; COMF04(); ....
That is, the client (developer) should not worry about the data binding, extraction logic etc. Instead, only specify Logical file, it’s keys with values, columns to be displayed, etc.
Similar way, my SDK app should be called without any data extraction logic etc. (like below code).
if (e.Key == Key.F4) { IInstanceHost child = theHost.CreateDialog(); BrowseControl bc = new BrowseControl(child); bc.Field = "BANO"; bc.AlternativeField = ""; bc.BrowseVariant = ""; bc.KeyFields = new String[] { "LMCONO","LMITNO","LMBANO" }; bc.KeyValues = new String[] { "0", "" }; bc.SearchText = txtUser.Text; //child.HostContent = bc; if (bc.ShowDialog().Value) { txtUser.Text = bc.SearchText; } }
Solution
In my solution, I’ve used CRS990MI program and its transactions to encapsulate data extraction from the developer. This MI Program will works based on defined browse definitions in MNS185 program.
The Transactions InitBrowse & LstBrowse are actually doing the work. You will understand this when we talk about the C#/WPF code. But for now, for your quick information, I summarized it as below.
- InitBrowse – Returns the browse definition of the search field with the columns headings. As in the above code , if you are going to search BANO (lot number ) , first we want to know what are the keys , key positions in order to get the BANO value. That is CONO (company) & ITNO(Item Number). Likewise, InitBrowse API provides us these metadata.
- LstBrowse – Gets data for the given search field (BANO) along with meta information from InitBrowse API.
In the next post (Part 2) I’m going to explain the C#/WPF Code.
Dec 6, 2016
Read Profile Settings from ISO SDK App
Background
Accessing Web Services, external data sources from a SDK app is common like other technologies do. To store these access points, parameters etc. can be done in various ways. In a .net application common scenario is store then in the .config file or setting file. Why we want to do like this is, avoid hassles of deployment. When ISO SDK application is considered, we can achieve same thing by using .manifest file.
Problem
I need to get database connection string from the M3 profile.
Solution
Sep 5, 2016
MEC: How to Set Message Counter for EDI Message
When you sending/creating EDI messages it is necessary to include unique message interchange number. This is to ensure each message that we are sending is unique.
In EANCOM/EDIFACT
Element 0020 of UNB segment:
UNB+UNOA:4+xxxxxxx:14+xxxxxx+20160905:0831+00000000000057+ +ORDERS++1'
In X12
Element ISA13 of ISA segment:
ISA*00* *00* *ZZ*167520391 *ZZ*39319445 *991201*1248*U*00200*000000001*0*P*>
This number need to be persistent. The middleware we are using for EDI transformation should cater this requirement. I used MS-BizTalk Server for two EDI projects, which cater the same. (just by a configuration)
M3 e-Collaborator (MEC) does the same thing in a different way. In the MEC database (e.g. MEC_Storage_TST) has a table (UTIL_Message_Counters) for this purpose.
Table structure is like this:
Note 1: To be able to use this class you must first create this table (use the SQL script MeC_Utilities_db_script.sql).
You don’t have to enter a record or write code to save/get data. Instead, you have to write 2 lines of java code in your mapper to get the Value. ( Unique Message Interchange Number)
Note 2: Values in Key fields are case sensitive.
Steps:
- Initialize the message counter for the map.
myMap is reference to the Map.
MessageCounter mc = new MessageCounter(myMap);
- Get a new counter value using one of 3 overloads
/* * getNewValue(String counterId) * counterID = Choose suitable name (max 20 chars) * * Returns new counter for the map */ String newVal = mc.getNewValue("MsgCounter");
Or
/* * getNewValue(String counterId, int keyFields); * counterID = Choose suitable name (max 20 chars) * * Returns new counter for the map AND parnter ID */ String newVal = mc.getNewValue("MsgCounter",mc.MAP_NAME + mc.PARTNER_ID);
Or
/* * getNewValue(String counterId, int keyFields, String cono, String divi, String date) * counterID = Choose suitable name (max 20 chars) * * Returns new counter for the map AND parnter ID AND cono AND divi AND date. * you can omit cono and divi by setting null * below code resets the counter for each day (format CCYYMMDD). */ String newVal = mc.getNewValue("MsgCounter",mc.MAP_NAME + mc.PARTNER_ID, null, null, DATE);
If, everything OK, you will return the new counter other wise –1.
If you look at the table (UTIL_Message_Counters) , a record has been added and value will be incremented each time when getNewValue() is called.
Aug 8, 2016
Compare 2 Word Documents
Microsoft Word came with a handy feature to compare 2 Word documents. But I’ve got to know this very recently.
Background
When I’m getting multiple revisions of the same MS-Word document, how can I make sure that I have seen the changes effectively?
Solution
Jul 22, 2016
MEC: Call Web Service in a cleaner way
Background
In the MEC mapper, calling a web service is a general scenario. There are few ways to do it. One method is build the SOAP request Payload in a string and submit via POST method. (as below code snippet)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
java.net.URL obj = new java.net.URL(iURL); java.net.HttpURLConnection con = (java.net.HttpURLConnection) obj.openConnection(); con.setRequestMethod("POST"); con.setRequestProperty ("Content-Type","text/xml"); con.setRequestProperty ("Accept","text/xml"); String itemStr = "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" + "<soap:Body>" + "<GetItem xmlns=\"http://tempuri.org/\">" + "<itemNumber>KelumG</itemNumber>" + "</GetItem>" + "</soap:Body></soap:Envelope>"; con.setDoOutput(true); java.io.DataOutputStream wr = new java.io.DataOutputStream(con.getOutputStream()); wr.writeBytes(itemStr); wr.flush(); wr.close(); |
This is very primitive and takes lot of times of developer. Also it hinders the code readability & maintainability.
From this post I’m going to tell you a cleaner way, rather simple way. We, programmers, know easy way to call web service is using Proxy objects/classes.
Proxy objects are type of representations of the web service for the programming language we are using.
Solution
- Create Proxy class from the web service.
The service I’m using for this post is http://localhost:4599/HelloService.asmx?wsdl (refer below P.S. section). There are few tools to create proxy classes in java (wsimport, axis2, java2wsdl etc. ). Here I’m using wsimport with following argument.
-d KG : store generated class into KG folderwsimport -d KG http://localhost:4599/HelloService.asmx?wsdlcommand to create proxy classes. - Create jar file for the generated files.
Using command line: https://docs.oracle.com/javase/tutorial/deployment/jar/build.html
Using Eclipse: http://help.eclipse.org/neon/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftasks-33.htm
Note:
There are limitations for customer JARs. ( Page # 85, Business Document Mapper, Version 11.4.3.0)
Package
To use a Java class from a Custom JAR in a mapping, the class has to use a package. The default package, that is no package, will not work. Note that you have to enter this package for all references to the custom class in the code for Java functions within a mapping.
Javadoc, encoding
If you want to get Javadoc in the mapping Java editor when using a Java class from a Custom JAR, the Java source code, that is, the .java file, must be included in the Custom JAR. The .java file must use the character encoding UTF-16, otherwise no Javadoc will be shown in the mapper. This is because the files for the mapping use that encoding.
- In the map add reference to this custom JAR file.
- Simply call the service just like a method.
1 2 3 4 5 6
private void callWebSvc() throws Throwable { // Please implement me org.tempuri.HelloService hs = new org.tempuri.HelloService(new java.net.URL(iUrl)); org.tempuri.HelloServiceSoap hsoap= hs.getHelloServiceSoap(); oItem = hsoap.getItem(iItem); }
P.S:
For this post I have created a mock web service (.asmx ) using C# and hosted in IIS. Sample code as below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
namespace WebServiceApp { [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] public class HelloService : System.Web.Services.WebService { [WebMethod] public string GetItem(string itemNumber) { return new ItemService().GetItem(itemNumber); } } public class ItemService { public string GetItem(string itno) { return string.Format("Item {0}",itno); } } |
MEC: How to Set Message Counter for EDI Message
When you sending/creating EDI messages it is necessary to include unique message interchange number. This is to ensure each message that we ...
-
In this post, I'm going to explain the step-by-step approach to configuring the popular development tool Postman to test/execute Inf...
-
You will find many posts/videos about this topic, but I intend to guide you step-by-step with more information to comprehend and also re...
-
I need to connect to a DB2 from a .net application. But it’s in iSeries system. I did not know what is the way do it. I read lot of article...