mercury worlds

Name Change Process

| Comments

Background

I found little information regarding the name change process in Mississippi. Most links were to websites to file the name change for you, or for buying forms, but not much in the way of the process, filing and notification requirements, and so on.

Think of everything that follows as “Hanna’s understanding is…”. I am not a lawyer and this isn’t legal advice. These are my experiences that I hope will help the next person. I have no affiliation with any of the web sites mentioned below, other than being a customer.

Forms and requirements

A citizen residing in Mississippi for more than six months has the legal right to change their name, so long as it is not done for a fraudulent purpose, such as evading creditors or crimes. The peititioner can have no outstanding judgements and (I think) cannot be a convicted felon. From my searching, the new name must be pronounceable (i.e., not a symbol a là Prince) and not profane.

There is no standard, state-required form. You could go to http://www.deltacomputersystems.com and look for other name change cases - many Mississippi counties, including Lafayette, where I live, file everything electronically. I took the convenience of using forms from http://www.uslegalforms.com/changeofname/, which came with filing instructions.

Most of the name change cases I saw included a copy of the petitioner’s birth certificate. Since the only birth certificate I had on-hand was a birth certificate card, went to https://www.vitalchek.com/birth-certificates and ordered a paper copy. It arrived in three days (paid for overnight shipping).

Double- and triple-check the spelling in the petition to avoid complications or denial of your petition. The court requires name change petitions to be notarized before filing. The instructions I used said have three copies of the petition and judgement filled in. Because my county files everything electronically, I only used one copy of the petition and judgement order.

Also recommended is filling out the Social Security card application from http://ssa-custhelp.ssa.gov/app/answers/detail/a_id/315/~/change-a-name-on-a-social-security-card, which is also used for changing the name in the Social Security system. The PDF can be filled in electronically and printed. I did this the day before court.

Filing

Take your notarized petition and paper birth certificate to the probate or chancery clerk’s office. If they file everything electronially, they will redact the Social Security number on the petition before scanning. The clerk will assign a case number, such as CV2013-025, which is the year and a sequential number. There will also be an (R) or (A) next to the case number, indicating whether the resident or attorney filed the petition. The filing fee in Lafayette County is $82.50, which includes filing fees and court costs.

After assigning the case number, the chancery clerk will give you the appointed judge, and the judge’s assistant’s number to schedule the hearing. Where I live, the chancery court only hears ex parte matters once a month, usually on the fourth Friday.

As far as I can determine, there are no publication requirements, before or after the name change. The instructions from U.S. Legal Forms, chancery judge, or clerk, did not indicate or order any publication.

Court day

I was scheduled to appear in court at 9:30am, when session begins. Reviewing the Delta Computer Systems site, I saw a muncipal bond issue, some probate and conservatorship cases, and a couple of name changes including mine. There was a young woman next to me, and a large group of people behind us.

The bond issue was heard first, raising some two million dollars for building upkeep and maintenance. As no one appeared in court to object, the bond passed and was signed by the judge.

Next was a conservatorship dispute, where accountancy of the conservatorship’s assets was not made. A restraining order preventing withdrawl of CDs (certificates of deposit) was put before the court. Lawyers on each side argued for several minutes. Eventually, the judge ordered a bond placed on the conservatorship and an accountancy completed in the next thirty days.

The group of people in the gallery left the courtroom, leaving only the young woman and myself. The judge asked if there was any other business before he called a recess. The woman approached the bench with her name change petition. Apparently she was living on her own or was estranged from her parents. As the age of majority in Mississippi is twenty-one, and she was eighteen years old, the judge denied her name change. He advised she could file to be emancipated (declared independent) from her parents, or wait until she was of majority age.

I approached the judge next with my petition and judgement order. The judge read it and the order, and signed the order without asking me any questions. Friends who went through name changes related experiences of the judge reiterating some of the items in the petition, especially about not changing the name for fraudulent purposes. Nothing of the sort in my case. He just signed the order, handed it back to me, reminded me to have the order filed with the clerk, and wished me a good day. It was done!

I left the courtroom and went downstairs to the clerk’s office to have the judgement filed. As with the petition, the judgement is filed electronically, so I only needed the original copy signed by the judge. The clerk made a second certified copy of me to give to other agencies. I don’t know how much copies usually cost, she gave me the copy free of charge.

First steps

For me, the most important things to have changed first are Social Security, my bank, my employer, driving license, and passport. My research indicated the DMV (department of motor vehicles) uses information from the Social Security agency. I was unsure about the bank, so start there first. I had to go there first, anyway.

The bank (1)

I talked with a bank manager about changing the name on my account. She indicated that the court order was not enough, that they look at Social Security information. In addition, I should wait until I have updated Social Security and the bank account before changing it at work. All this is due to the Patriot Act, you see. All privacy-driven and proper. That’s fine. I just need to get into my safe deposit box to retrieve my Social Security card and passport.

So I go to the desk to sign in for my box. The lady at the desk has worked with me before and has let me in my box before. But I wasn’t presenting female then and not wearing makeup. I sign in and hand her my driving license. She pauses, asks me to wait a moment, and goes to talk to a manger. After several (five? ten?) minutes, she comes back and says she can’t let me into my box. I don’t resemble enough my likeness on the license. Did I have any other government-issued ID with an up-to-date likeness? No; the only other ID was my passport in the box.

I wasn’t being allowed into my box to get my Social Security card, so I could update it with a new name, get a new license, and then come back to the bank and update my account. She said I should be able to go to the DMV with my court order and birth certificate (which I had with me) and get a reissued license. I was upset then, defeated at the first gate. I decided to go to the DMV to see if they would reissue my license.

DMV

I calmed down by the time I arrived at the DMV. Went inside and was seen immediately. I showed the clerk my court order and expressed my desire to have my license reissued. She said they couldn’t change the name with just a court order, but that Social Security had to be updated, that is how they determine which name to use. Of course, I was just denied entry to my box to get my Social Security card so I can update my records and get a new license….

I asked if they could reissue it with the same information but a new picture? Sure, they could do that, eight dollars please. Five minutes later I had an ID with my new likeness, back to the bank…

The bank (2)

OK, I can finally get into my box. Time is growing short, because I need to be at a Social Security office by 3pm.

I go back to the box desk, here’s my ID, can I please get in my box? My ID and my likeness match, I’m using my old name to sign in, but… she takes my info and ID and goes to talk to a manager again. Maybe five minutes later she is back and starts looking up something in the computer.

She hands me a sheet of paper with my secret questions, would I please answer them? Of course, easy as pie. Oh and if I would sign my name five times (presumably to ensure my signature is the same as that on the sign-in form). See how secure we are? We are protecting you! Finally, she retrieved the bank’s box key and led me into the vault. I retrieved my Social Security card and passport, and left. I had to get to Memphis (well, not really, but you’ll see why below).

Social Security office (1)

Fueled up and headed to Memphis. Several of my friends raved about the friendlyness of the Social Security office in Germantown. I needed a break today. It’s difficult to believe the easiest part of the name change was getting the judge’s signature!

Drove up to the Social Security office in Germantown. It’s eeriely silent. Walked to the door. The office closed permanently in December 2012, please visit one of our other locations. This is like a comedy of errors. Comedy from the outside only. It’s 2pm and I have an hour to make it downtown in rush hour. I feel like I’m in an episode of 24.

Social Security office (2)

Fortunately, I already knew where the office was in midtown Memphis. The most straightforward way was to hop on Poplar and head west. No real problems until I got to the Poplar-Perkins intersection. We sat through two light cycles, and the traffic barely moved. Turns out there was a wreck in the inside lane (my lane). I went in the turning lane and turned onto Perkins south, and cut over on Spottwood. Go around Oak Court Mall and pick up Poplar again. Make it to midtown and finally at the office.

I check in and get my printed ticket. It’s 2:50pm and there’s a waiting room full of people. But, things are moving pretty quickly. 3pm goes by and the guard locks the outside door. Those of us that signed in would be processed. Hurray! My number is called and I give the clerk my judgement order, application (filled in and printed out earlier), and old Social Security card. While I wasn’t required to have the old card, it makes the process quicker if I did have it. The clerk took the card and gave me a printout showing the application was entered. I should receive the new card in a few days.

Afterword

It’s been a day and a half and it’s still hard to believe I’ve done it! Just running around on Friday didn’t give me time to think about this achievement. All I can think of is, wow.

I hope the Social Security electronic records are updated in the next couple of days, so I can get my real updated driving license in the next week. I hope I don’t need the physical card to get a new license.

Starting With Git

| Comments

My last brush with source control was years ago with Microsoft’s Visual SourceSafe. Circa 2003, I found it very lacking and poor performing. We were mandated to use it to house our source (classic ASP and early .NET), we ran monthly log reviews against the repository. It wasn’t pleasant to work with.

Around this time, we installed Aldon change management system on our IBM iSeries (that is what our box was called at the time; IBM has rebranded it to System i, which has to be one of the most unfriendly Google search terms ever). Aldon is a centralized RCS, written to take advantage of the unique features of the iSeries / System i. It uses the familiar checkout/checkin process, but has worked very well. We’ve had no problems with it.

So I’m trending back into extracuricular programming and has happy to see projects like Git and Mercurial (ha!) reach the next stage of source versioning. I was aware when Linus Torvalds switched to BitKeeper, it made big waves in the open source community. And was not totally surprised when Bitkeeper changed their agreement with the Linux kernel dev community and discontinued the free repository. Chillingly ironic that Linus wasn’t offered a professional account, given that Bitkeeper was inspired by the desire to streamline Linus’ workflow with source code management.

Anyway, like I said in an earlier post, I was looking for a new blogging and hosting solution and came across Octopress and GitHub. And happily, GitHub can host static sites, which is fine with me since many blogs are 95% essentially static content.

Now I’m learning about Git and love it so far. Learning about Ruby again, it’s been quite a few years since I used it. One of the first projects I wanted to try was writing RPG (IBM Report Program Generator) and UIM (IBM User Interface Manager tag language) lexers for Pygments. Alas, to learn that Pygments is written in Python (yes, the Py… is a dead giveaway), and adding insult to injury, the main repository is in Mercurial (ha! again). To be an effective contributor, I should be familar with Hg. The saving grace is it seems the syntax (git|hg clone, git|hg add, git|hg commit) is seemingly identical. Unsurprising that both projects started as a reaction to the BitKeeper debacle and probably the two projects (Git and Mercurial) feeding off each other and performing the same functions as a DSCM.

That was the really long way of saying I found the following helpful learning about Git. I’m interested in hearing if the same source tree can be managed by both Git and Mercurial, with each SCM ignoring the other’s .git or .hg directories. Hmmm.

edit: I just found this link which confirms my thought processes: http://programmers.stackexchange.com/questions/104786/having-a-git-repo-and-mercurial-in-the-same-directory:

Just put .hg in .gitignore (and .git in .hgignore) and you are more than good to go.

The only real downside is storing the repository twice… but disk is cheap. Remember to push the source to both remotes, that’s what a shell script is for. So I can go about pushing the same source to GitHub and BitBucket. Cool!

Oh, and why Mercurial gets a “ha” from me? Mercurial goes by the abbreviation Hg (the symbol for Mercury), and that happens to be my initials as well! Maybe I should go by the alias hydrargyrum.

–Hg

Octopress Resources

| Comments

Just a list of resources I found useful when setting up Octopress. I’m by no means done, and will add to the list.

2013/01/04

Moving blackrobes.net Content

| Comments

I’m on the fence deciding how to handle my personal site, blackrobes.net. It’s a mix of blog, code, and other random stuff. Thinking about moving the code into GitHub and referencing on my user page, and putting the blog stuff on a new blackrobes.net site hosted on GitHub. The biggest hurdle is handling redirects. I want pages, such as http://blackrobes.net/code/uim-brush-file-for-syntaxhighlighter, to redirect to https://github.com/hannagoodbar/syntaxhighlighter-hg.

But it will take time to migrate the content over, and I’m not worried as much yet. Just thinking out loud…

Before I Continue…

| Comments

So I did a couple of stupid things this morning. I wanted to change my user name, glittergirlhanna is too social for GitHub, so I renamed the account to hannagoodbar. Then I renamed my repo, and the local repo (here is where the mistake is), then pulled from GitHub to make sure everything worked. It worked… and I could no longer do rake new_post[]. Oops, I forgot to sync the Octopress source to GitHub, even though it told me in plain sight to do so!

Don’t forget to commit the source for your blog.

git add .
git commit -m 'your message'
git push origin source

Luckily, I only made two blog posts before I decided to do all this. Lesson learned, again. Before you do something for which you don’t know the outcome, make a backup! Make a backup.

Until next time…

Moving Web Hosts to GitHub

| Comments

Ancient history

So, I’ve done a little bit of web stuff, mostly blogging, since the early 2000’s. I forget when I registered the domain blackrobes.net, but I was serving pages in-house from what was called ClarkConnect, now called ClearOS. ClarkConnect was/is a RedHat Linux based gateway, router, firewall. I installed MySQL for a database server and wrote hand-coded HTML pages for a blog.

One can hand-code HTML for only so long, and I searched for a blogging platform and ended up using b2 for a while, which eventually became WordPress. At the time, b2 and WordPress were small and simple, and I made some contributions to the code base.

Wordpress took off, became better but more complicated to use. It became popular very quickly. Plugins were introduced, and it became the target for site attacks. And each release became a little slower. (I think WP did a revamp of the core engine to increase responsiveness.) But I felt too removed from making things work. Maybe it’s a little bit hipster, but I wanted something new, different, faster, and lesser-known. During my WordPress era I moved the site from in-house servers to a hosted service, Just Host. They, like most hosting services, allow full access for scripting, database storage, and managing HTML.

In 2009-2010 I took a look at TextPattern, a CMS package structured around periodicals publishing. Security was managed in levels, such as writer, editor, publisher, and designer. They have clear roles in the software, and though I didn’t take advantage of them, I liked how the software was intended to be used. Site structure was managed in the CMS, with HTML templates called pages and reusable snippets called forms. The engine was context-aware, making pages and forms very powerful. I redeployed blackrobes.net in TextPattern in 2011.

Present day

I haven’t blogged much in recent years but changes in my life led me to start looking at technology again. I signed up with Tumblr (see me at http://glittergirlhanna.tumblr.com) for more of my “social” blogging. I also want something separate for more tech-y stuff. I read a story about a guy running his blog on a Raspberry Pi and noticed he was running Octopress. Octopress’ philosophy is to serve static content, instead of dynamically-generated content from TextPattern and WordPress. Octopress has documentation for deploying to various hosts, including GitHub. After reading other success stories with Octopress and GitHub, I decided to use that as my new blogging platform.

It took me a while today to get everything set up (I use a MacBook Air running Mountain Lion), since I’ve not used my command-line skills in several years. I want to learn more about Ruby, so having Octopress makes it nice to have example code.

The world is still spinning round

It seems I’ve come full-circle. I started off with hand-coded, static HTML files for my blog, went into several years of running a dynamic website, and now I’m back to creating static files. But this time I have help in the form of Markdown, Octopress, and GitHub. The more things change…

Ciao!

Integrating SyntaxHighlighter and TextPattern

| Comments

SyntaxHighlighter is a nice JavaScript-based code highlighter I’ve used for several years, and integrated into TextPattern for the blackrobes.net site, but I haven’t documented the process until now.

Integrating SyntaxHighlighter uses the soo_required_files and soo_plugin_pref plugins. You can find them at http://ipsedixit.net/txp/74/soo_required_files. Install and activate both, keeping the default settings.

Install SyntaxHighlighter in the document root /syntaxhighlighter. No special configuration is needed. SyntaxHighlighter can be found at http://alexgorbatchev.com/SyntaxHighlighter/.

In TextPattern, make a custom field called Requires. By default this is the name soo_required_files uses for per-article script loading.

Add the following forms to the Miscellaneous category to enable SyntaxHighligher scripting functions. The form require_sh_head loads all the necessary SyntaxHighligher processing scripts into the page. Brush files are loaded later, as called for by the article.

require_sh_head
1
2
3
4
<!-- form misc/require_sh_head -->
<script type="text/javascript" src="/syntaxhighlighter/scripts/shCore.js"></script>
<link rel="stylesheet" type="text/css" href="/syntaxhighlighter/styles/shCore.css" />
<link rel="stylesheet" type="text/css" href="/syntaxhighlighter/styles/shThemeDefault.css" />

The form require_sh_activate will be called by the article to indicate SyntaxHighlighter should be activated for the article.

sh_activate
1
2
<!-- form misc/require_sh_activate -->
<script type="text/javascript">SyntaxHighlighter.all();</script>

Create forms for any brush files. I name these require_shb_brushname, where shb is a brush file is needed, whereas sh designates a SyntaxHighlighter need. All the brush file forms are similar and only load one brush each.

require_shb_plain
1
2
<!-- form misc/require_shb_plain -->
<script type="text/javascript" src="/syntaxhighlighter/scripts/shBrushPlain.js"></script>
require_shb_javascript
1
2
<!-- form misc/require_shb_javascript -->
<script type="text/javascript" src="/syntaxhighlighter/scripts/shBrushJScript.js"></script>
require_shb_html - aliased to Xml brush
1
2
<!-- form misc/require_shb_html -->
<script type="text/javascript" src="/syntaxhighlighter/scripts/shBrushXml.js"></script>

In the article, put the brush name, such as shb_javascript, and sh_activate, each separated with commas, into the Requires custom field. It is recommended that sh_activate is placed last. You do not need to include the require_ because it is added by soo_required_files.

Requires example
1
shb_html, shb_plain, sh_activate

The brushes in the Requires field must correspond with the brush requested in the article. For example, requesting the JavaScript brush should have the corresponding Requires name.

SyntaxHighlighter can be used with either <script> or <pre> tags. THe advantage of the <pre> tag is the text can be seen by RSS readers and in places where scripting is disabled, but requires that the less-than opening bracket character < be replaced with the entity &lt;. Using the <script> along with <[CDATA[]]> means most anything can be used as-is, but will be invisible to RSS readers and places where scripting is not active. Both examples are shown below.

Article brush request example with script tag
1
2
3
4
notextile.. <script type="syntaxhighlighter" class="brush:html;" title="Paragraph example">
<![CDATA[
<p>This is a paragraph.<p>
]]></script>
Article brush request example with <pre> tag
1
2
3
notextile.. <pre class="brush:html;" title="Paragraph example">
&lt;p>This is a paragraph.&lt;/p>
</pre>
Corresponding Requires brush request
1
shb_html, sh_activate

Will render as

Paragraph example
1
<p>This is a paragraph.</p>

When using HTML- or XML-like brushes, sometimes tags such as cause problems rendering in SyntaxHighlighter; the most common symptom is a partial or nonrendered highlight, or unwanted characters after the highlight. In this case, use the XML entities such as &lt;: using &lt;/script> will render as </script>.

Three Ways I Called an RPGLE Program From Java

| Comments

A recent project had me comparing different ways to call an RPGLE program using Java. I am a newbie / novice Java programmer, so this gave a lot of insight into the Java language and some of the JT400 / JTOpen tools.

To start, I had this RPGLE program. It retrieves, increments, sets, and returns a general ledger (GL) journal entry sequence number.

RPGLE program to get next GL sequence
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  // Program: incgljseq
  // Retrieve last used journal entry sequence; increment and store;
  // return new sequence.
 Fdbaxrel0  UF   E           K DISK

 d incgljseq       pr                  extpgm('INCGLJSEQ')
 d inlocation                     5a   const
 d outuseseq                     10i 0

 d incgljseq       pi
 d inlocation                     5a   const
 d outuseseq                     10i 0

 d sequence        s             10i 0

  /free

     sequence = 0;
     chain inlocation @axrecd;
     if %found;
        axlgnb += 1;
        sequence = axlgnb;
        update @axrecd;
     endif;
     outuseseq = sequence;
     *inlr = *on;
     return;

  /end-free

Originally, I intended to call the program using a stored procedure. In the course of the project I decided to pursue calling the RPGLE program directly. In the end, I called the program using PCML, but would consider JDBC due to its brevity.

SQL stored procedure definition
1
2
3
4
5
6
7
8
create procedure rtvgljseq
(in location char(5),
 out newseq integer)

external name incgljseq
language rpgle
parameter style general
;

The integration tool I was using, Extol Business Integrator, has special parameter requirements when using Java programs a particular way. Because of this, I used the main() method as a testbed, enabling me to call the program from the command line, and later in Eclipse when developing the other calls.

I investigated three different ways to call the RPGLE program: using ProgramCall (call the program directly), ProgramCallDocument (call the program using PCML, which is like a prototyped call), and JDBC. The main method is the same for all three classes.

Java main() template
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args) {

  // Exerciser program.
  Object[] parms = new Object[5];

  // parms[0] receives the output, nextSequence
  parms[1] = "192.168.0.1"; // IP address of IBM i system
  parms[2] = "USERID"; // user id to sign on
  parms[3] = "PASSWORD"; // password for user id
  parms[4] = "LOC"; // location from which to retrieve the next sequence

  try {
      System.out.println("Input : '" + parms[4] + "'");
      execute(parms, null, null);
      System.out.println("Output: '" + parms[0] + "'");
  }
  catch (Exception e) {
      System.out.println(e.toString());
      e.printStackTrace();
  }
}

For all three classes, the execute() method calls the RPGLE program and returns the next sequence. First, here is the call using ProgramCall.

RPGLE call using ProgramCall
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public static synchronized void execute(Object[] parms, StateTableInstructionState stis, MethodMessages mm) {

  int nextSequence = 0;
  String sysname = (String) parms[1];
  String userid = (String) parms[2];
  String password = (String) parms[3];
  String vanguardLocation = (String) parms[4];
  AS400 sys = new AS400(sysname, userid, password);

  try {
      String msgId, msgText;

      // Set up library list for program call.
      CommandCall command = new CommandCall(sys);
      if (command.run("CHGLIBL LIBL(PROD_MOD VNGDBDTA)") != true) {
          AS400Message[] messageList = command.getMessageList();
          for (int i = 0; i < messageList.length; i++) {
              msgId = messageList[i].getID();
              msgText = messageList[i].getText();
              System.err.println(msgId + " - " + msgText);
          }
      }

      // Create field types for parameters.
      AS400Text txt5 = new AS400Text(5);

      // Create parameter array and populate.
      ProgramParameter[] parmList = new ProgramParameter[2];
      parmList[0] = new ProgramParameter(txt5.toBytes(vanguardLocation));
      parmList[1] = new ProgramParameter(4);

      // Set up program call and run.
      ProgramCall pgm = new ProgramCall(sys, "/QSYS.LIB/PROD_MOD.LIB/INCGLJSEQ.PGM", parmList);
      if (pgm.run() != true) {
          AS400Message[] messageList = pgm.getMessageList();
          for (int i = 0; i < messageList.length; i++) {
              msgId = messageList[i].getID();
              msgText = messageList[i].getText();
              System.err.println(msgId + " - " + msgText);
          }
      } else {
          AS400Bin4 bin4Converter = new AS400Bin4();
          byte[] data = parmList[1].getOutputData();
          nextSequence = bin4Converter.toInt(data);
      }
  } catch (Exception e) {
      System.err.println(e.getMessage());
      e.printStackTrace();
  }

  sys.disconnectAllServices();
  parms[0] = Integer.toString(nextSequence);
}

Don’t worry about the execute() method declaration; that is special for Extol Business Integrator (EBI). Also disregard the conversion of nextSequence from integer to string; again, this is to work around an issue I had with EBI.

The ProgramCall code has lots of parts: conversions from Java to IBM i (AS/400) data types and back, setting up the library list, and handling for retrieving IBM i error messages if necessary.

A little shorter way is to call using PCML. PCML is a tagged document similar to XML which is a “prototype” for calling an RPGLE program from Java. For more information about compiling a program to generate the PCML file see the post.

The PCML file defines the interface to the called program, including the program’s location, and number and type of parameters. The PCML’s file name is incgljseq.pcml.

PCML for INCGLJSEQ
1
2
3
4
5
6
7
8
9
10
<pcml version="4.0">
   <!-- RPG program: INCGLJSEQ  -->
   <!-- created: 2009-10-30-13.26.10 -->
   <!-- source: LOYD/SOURCE(INCGLJSEQ) -->
   <!-- 18 -->
   <program name="INCGLJSEQ" path="/QSYS.LIB/LOYD.LIB/INCGLJSEQ.PGM">
      <data name="INLOCATION" type="char" length="5" usage="input" />
      <data name="OUTUSESEQ" type="int" length="4" precision="31" usage="inputoutput" />
   </program>
</pcml>

And here is the Java code to call using PCML. We do not have to give the PCML’s extension when passing the file name into ProgramCallDocument. Under the covers, the method looks for a serialized version with extension .pcml.ser, or the regular file with extension .pcml.

RPGLE call using PCML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public static synchronized void execute(Object[] parms, StateTableInstructionState stis, MethodMessages mm) {

  int nextSequence = 0;
  String sysname = (String) parms[1];
  String userid = (String) parms[2];
  String password = (String) parms[3];
  String vanguardLocation = (String) parms[4];
  AS400 sys = new AS400(sysname, userid, password);

  try {
      String msgId, msgText;
      // Set up library list for program call.
      CommandCall command = new CommandCall(sys);
      if (command.run("CHGLIBL LIBL(PROD_MOD VNGDBDTA)") != true) {
          AS400Message[] messageList = command.getMessageList();
          for (int i = 0; i < messageList.length; i++) {
              msgId = messageList[i].getID();
              msgText = messageList[i].getText();
              System.err.println(msgId + " - " + msgText);
          }
      }
      ProgramCallDocument pcml = new ProgramCallDocument(sys, "incgljseq");
      pcml.setValue("INCGLJSEQ.INLOCATION", vanguardLocation);
      pcml.setValue("INCGLJSEQ.OUTUSESEQ", nextSequence);
      if (pcml.callProgram("INCGLJSEQ") != true) {
          AS400Message[] messageList = pcml.getMessageList("INCGLJSEQ");
          for (int i = 0; i < messageList.length; i++) {
              msgId = messageList[i].getID();
              msgText = messageList[i].getText();
              System.err.println(msgId + " - " + msgText);
          }
      } else {
          nextSequence = (Integer) pcml.getValue("INCGLJSEQ.OUTUSESEQ");
      }
  }
  catch (Exception e) {
      System.err.println(e.getMessage());
      e.printStackTrace();
  }
  sys.disconnectAllServices();
  parms[0] = Integer.toString(nextSequence);
}

Finally, here is the call using JDBC, using the stored procedure definition listed above. It has by far the fewest lines of code, and eliminates the need for multiple conversions from Java types to IBM i types. It also elminiates the need of a separate call for setting the library list. (This can be done by calling a CL program wrapper, but this exercise is calling the RPGLE program.) One disadvantage of JDBC is being limited to using “simple” parameter types. Contrast with the PCML call, which can use complex parameters, such as RPG data structures.

RPGLE call using JDBC
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static synchronized void execute(Object[] parms, StateTableInstructionState stis, MethodMessages mm) {

  int nextSequence = 0;
  String sysname = (String) parms[1];
  String userid = (String) parms[2];
  String password = (String) parms[3];
  String vanguardLocation = (String) parms[4];

  try {
      DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver());
      Connection conn = DriverManager.getConnection("jdbc:as400://" + sysname + ";naming=system; libraries=,prod_dta,prod_mod,vngdbdta", userid, password);
      CallableStatement cs = conn.prepareCall("call rtvgljseq(?,?)");
      cs.registerOutParameter(2, java.sql.Types.INTEGER);
      cs.setString(1, vanguardLocation);
      cs.execute();
      nextSequence = cs.getInt(2);
      cs.close();
  }
  catch (Exception e) {
      System.err.println(e.getMessage());
      e.printStackTrace();
  }
  parms[0] = Integer.toString(nextSequence);
}

My preference is to use either PCML or JDBC. The JDBC code is very brief and hides or elminiates variable casting. However, it is really suitable for simple parameter types, and requires an extra IBM i object (the stored procedure definition). PCML is nice because like JDBC, it describes the number and kind of parameters. However, there is a separate system connection and call to set the library list if needed. Like JDBC an extra object is needed (the PCML file) but rather than server-side, it is bundled with the Java code.

This post pulled together and briefly compared various ways to call an ILE RPG program from Java.

Links:

Coding Java Programs for EBI External API Actions

| Comments

In Extol Business Integrator (EBI), coding requirements for External API Actions (implemented via Java programs) are different from a Business Process task Run Java Program. The Run Java Program task can execute any method from a class or JAR file with any parameter combination. In contrast, External API Actions have specific parameter requirements.

Java structure for External API Actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import com.extol.engines.StateTableInstructionState;
import com.extol.engines.MethodMessages;

public class MyClassApi implements Serializable {

  public static synchronized void execute(Object[] parms, StateTableInstructionState stis, MethodMessages mm) {
      // parameters passed in Object[] parms - these map to EBI
      String parm1 = (String) parms[1];
      String parm2 = (String) parms[2];

      ...

      // method body

      ...

      parms[0] = someReturnValue; // return value
  }

  // empty main method...
  public static void main(String[] args) {
  }

  // or use as testing, call from command line...
  public static void main(String[] args) {

      // Exerciser program.
      Object[] parms = new Object[3];
      
      // parms[0] receives the output, nextSequence
      parms[1] = "my parm 1";
      parms[2] = "my parm 2";
      
      try {
          execute(parms, null, null);
          System.out.println("Output: '" + parms[0] + "'");
      }
      catch (Exception e) {
          System.out.println(e.toString());
          e.printStackTrace();
      }
  }
}

The two import lines are required for communications between EBI and the Java program when used as an External API Action.

The class definition should implement Serializable.

Extol discourages the use of the main() method. Other coding examples I’ve seen use execute() as the method name. Obviously, if you have multiple methods in your class/JAR file, they will have different names.

When defining the External API Action in EBI, your mapped parameters correspond to the Object[] parms parameter. By Extol convention, if there is a (single) return value, it is passed in parms[0].

I use the main() method to call from Eclipse or the command line for testing, and set up the parameters the same way as they are expected to be used in EBI.

It is recommended (at least for EBI 2.4, as of this writing) that return values be type String. When used in an EBI transformation ruleset, output type of Integer cannot be mapped to a corresponding middle tree variable, resulting in a type mismatch error message.

Update 5 Nov 2009: If an External API Action definition is changed, any rule sets referencing it must be updated. Open the ruleset and select Tools, Refresh Action Lists. Then validate, compile, and save the rule set. The reason for this is because the ruleset is compiled into a Java class, and any external API actions are integrated at compile-time.

This article was originally published on 2 Nov 2009.

ILE RPG ReplaceXmlEntities()

| Comments

Use this subprocedure when you need to escape common XML entities & (ampersand), < (less than), > (greater than), ‘ (single quote), and ” (double quote). Several web reports I generate using CGIDEV2 are in HTML or XML form, and those special XML characters must be escaped.

Author’s note: please excuse the old SyntaxHIghlighter format. I hope to write a lexer for Pygments.

  1.       // Variables for XML entity replacement.  
  2.      d xmlentities     s              1a   dim(5) ctdata  
  3.      d xmlreplacement  s              4a   dim(5) alt(xmlentities)  
  4.   
  5.       // Prototype.  
  6.      d ReplaceXmlEntities…  
  7.      d                 pr           400a   varying  
  8.      d  invalue                     200a   options(*varsize) const  
  9.   
  10.       // Subprocedure.  
  11.      p ReplaceXmlEntities…  
  12.      p                 b  
  13.   
  14.      d ReplaceXmlEntities…  
  15.      d                 pi           400a   varying  
  16.   
  17.      d  invalue                     200a   options(*varsize) const  
  18.      d lastpos         s             10i 0 inz  
  19.      d start           s             10i 0 inz  
  20.      d workvalue       s            400a   inz varying  
  21.      d z               s             10i 0 inz  
  22.   
  23.       /free  
  24.   
  25.          // See the XMLEntities CTDATA array for list.  
  26.          // Ampersand (&) should be first because that is what all the  
  27.          // other replacements use.  
  28.          workvalue = invalue;  
  29.          for z = 1 to %elem(xmlentities);  
  30.              lastpos = 0;  
  31.              start = 1;  
  32.              lastpos = %scan(xmlentities(z):invalue:start);  
  33.              dow lastpos > 0;  
  34.                  workvalue = %replace(‘&’+%trim(xmlreplacement(z))+’;’ :  
  35.                    workvalue:lastpos:1); // ”:1” overwrites the existing “bad” char  
  36.                  start = lastpos+1;  
  37.                  lastpos = %scan(xmlentities(z):invalue:start);  
  38.              enddo;  
  39.          endfor;  
  40.          return workvalue;  
  41.   
  42.       /end-free  
  43.   
  44.      p ReplaceXmlEntities…  
  45.      p                 e  
  46.   
  47.       // Compile-time data.  
  48.       // This can also be stored in a D-spec array.  
  49. **CTDATA xmlentities  
  50. &amp  
  51. <lt  
  52. >gt  
  53. ‘apos  
  54. “quot  

Feel free to change the size of the invalue, workvalue, and return sizes. I use the procedure over single fields of data which are not very large.