Tag Archives: M3

Java Debugging an Infor Grid application at runtime

Here is an illustrated example of how to use the Java Debugger in Eclipse to debug an existing Infor Grid application at runtime for which we don’t have the source code; for example I will debug the M3 Web Services (MWS) server, line by line, while I make a SOAP request.

For that, I will use the technique I learned in my previous post, Hacking Infor Grid application development (part 6), where I learned how to use the Java Debugger for my own Grid application for which I had the source code, and I will extend that technique to an existing Infor Grid application for which I don’t have the source code but for which I have the JAR files.

I had to learn this technique in order to troubleshoot a timeout issue we are currently having in MWS when making a SOAP request. This helped me pinpoint the modules, packages, classes, methods and lines of code that were at cause and report the results to Infor Support so they can report them to Infor Product Development for help. To that effect, please join the campaign and sign the petition asking Infor Product Development to make their source code available so we can better troubleshoot issues and learn. Also, this week is Open Access Week and it’s a great opportunity to ask Infor to make more of their documentation available.

Logging and DEBUG level

In order to narrow down the search space for the issue I was troubleshooting, I increased the log level of the application’s node to DEBUG level. In my case, I selected ALL modules: SYSTEM and MWS. I had also selected TRACE but it didn’t produce any log.
2

I then opened the log file and found interesting information about the bottleneck issue, that helps me narrow down which modules, packages, and classes to debug. In my case they are: MWS com.lawson.webservices.m3.program.M3Session, and SYSTEM DistributedLock:
2_

Remember to revert the log level changes after you’re done to avoid clogging the disk space with increasing log.

Setup the Java Project in Eclipse

Let’s setup a new Java Project in Eclipse with the JAR files of the Infor Grid application (e.g. MWS in my case). For that:

  1. Create a new Java Project in Eclipse, give it a name, and select Add External JARs:
    1.6_
  2. Select the JAR files of the Infor Grid application in LifeCycle Manager (e.g. MWS\lib\*.jar in my case):
    1.7
  3. Optionally, you can also add the JAR files of the Grid runtime (grid-core.x.y.z.jar, etc.).
  4. Open the desired Java class (double-click), Eclipse will open that class in the Class File Editor, and for now it will say “Source not found”, we will fix that later:
    1.11

Start debugging

Now let’s debug the application, even without the source code:

  1. Toggle the breakpoints at the desired methods:
    2.0
  2. Prepare the Infor Grid application for debugging as detailed in my previous post:3
  3. Start debugging in Eclipse:
    2.1_
  4. Make the application go through your breakpoint (in my case I make a SOAP request, the application will call M3Session.logon, and Eclipse will suspend at my breakpoint).
  5. At this point, even without the source code, you can use the debugger as usual, to execute line by line, inspect variables, evaluate expressions, etc.; each class will show “Source not found” for now:
    2.6

Add the Java decompiler

Now let’s use a Java decompiler for Eclipse to recover the source code (not the original source code though) and attach it to the classes.

  1. I installed the JD-Eclipse plugin by Emmanuel Dupuy:
    0
  2. JD-Eclipse will change the file association in Eclipse to open class files that don’t have source, decompile them, and attach the decompiled source back to the class:
    1.9
  3. Also, JD-Eclipse will realign the line numbers of the recovered source code so they match with the debug information of the class, otherwise the debugger will show the wrong lines of source code and it will be very confusing:
    1.10
  4. Now open a class file (double-click) and JD-Eclipse will show the recovered source code with line numbers realigned:
    2.1
  5. Now debug again with the breakpoints. This time the debugger will show the source code. This is the ideal scenario for debugging line by line:
    3.3

Problem

I realized that as I’m debugging, JD-Eclipse will not decompile classes which it hasn’t previously decompiled. So if the debugger steps through a class that hasn’t been previously decompiled, the debugger will show the usual “Source not found”.

The workaround is to open all the classes we need the source code for, prior to debugging, one by one, so JD-Eclipse can decompile them, and attach the source code back to the class, and then we can try debugging again.

UPDATE 2014-10-29: That is not true anymore, and I found the solution: we have to change the default file association for the *.class files in order to use Java Decompiler’s Class File Editor, and we must do so every time we start Eclipse because Eclipse will revert to the default Class File Viewer when we exit Eclipse:
0

Future work: batch decompilation with realignment

I tried the plugin Realignment for JD-Eclipse by Alex Kosinsky that does batch decompilation, but it doesn’t realign the line numbers, so that doesn’t work. I also tried the plugin JDEclipse-Realign by Martin “Mchr3k” Robertson, it does decompile, and it does realign the line numbers, but I couldn’t get the source code to show while debugging, even after having previously decompiled the class, and I don’t know if it does batch decompilation.

UPDATE 2014-10-29: Also, I tried Java Decompiler’s > Save All Sources, but it doesn’t realign the line numbers, even though JD-Core’s change log for version 0.7.0 says “Added an algorithm to realign the decompiled source code to the original line numbers”:
y

That’s future work to solve.

Summary

That was an illustrative guide of how to do Java debugging on an Infor Grid application, at runtime, without having the source code of the application, having just the JAR files from LifeCycle Manager. This technique helped my troubleshoot an issue with MWS. I hope it will help you too.

That’s it! If you learned something, please click Like below, click Follow to receive notifications about new blog posts, share around you, sign the petition, and write the next blog post with me, you are great. Thank you.

Tagged , ,

Hacking Infor Grid application development (part 6)

Here is the sixth article in the series on Hacking Infor Grid application development, and today I will illustrate how to debug the Grid application at runtime. This is useful for development and troubleshooting purposes. For that, I will use the standard Java Platform Debugger Architecture (JPDA) that is included in Java.

I will do the illustration gradually: I will start by debugging a simple HelloWorrrld class from the command line, then I will debug it remotely, then I will debug it from Eclipse, and finally I will debug the Infor Grid application.

Remember the intention is to hack ethically, to learn and to push the boundaries of what is possible. Also, remember to join the campaign and sign the petition asking Infor Product Development to make their source code available so we can do better work. Also, next week is Open Access Week, and it is a great time to ask Infor Product Development to make more of their documentation available.

Debugging from the command line

Here is a quick illustration of how to use jdb, the Java Debugger, to debug a simple HelloWorrrld class from the command line.

Here is the simple HelloWorrrld class:

public class HelloWorrrld {
    public static void main(String[] args) {
        int i = 11;
        int j = 13;
        int k = i * j;
    }
}

Suppose we want to debug the class at runtime and set a breakpoint at line 6 to see the value of variable k.

For that, we compile the class with the -g command line parameter to generate all debugging information, including local variables; by default, only line number and source file information is generated:

javac -g HelloWorrrld.java

Then, we have jdb launch a new Java Virtual Machine (VM) with the main class of the application to be debugged by substituting the command jdb for java in the command line:

jdb HelloWorrrld

Then, we set the breakpoint at line 6:

stop in HelloWorrrld:6

We could have also stopped execution at the beginning of the main method instead of at a specific line number:

stop in HelloWorrrld.main

Then, we start the execution of the debugged application:

run

The debugger will execute up to the breakpoint, at which point we can display the value of k:

print k

It will display k = 143.

Then, we advance execution to the next line and so on until the end:

step

Here is a screenshot of the steps:
1

Debugging remotely

Now I will illustrate how to debug the same class remotely by attaching jdb to a Java VM that is already running.

First, we find a port number that is available on the host where we will run the class, for example I use netstat, and for example I will try port number 1234:

netstat -an | findstr :1234

If netstat returns LISTENING then that port number is already in use and unavailable; otherwise you can use it.

Then, we start the Java VM (the debuggee) with the following options to load in-process debugging libraries and specify the kind of connection to be made and allow jdb to connect to it at a later time:

java -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:1234,server=y,suspend=y HelloWorrrld

-agentlib:jdwp loads the native agent library for the Java Debug Wire Protocol (JDWP).
suspend=y makes the JVM wait on startup for a debugger to attach before running.
transport=dt_socket sets the transport specification to socket transport using a single stream TCP/IP connection between the debugger application and the target VM.
address=1234 is the port number to which the debugger should attach to the JVM. This number should normally be above 1024. Verify that it is available.
server=y indicates that the JVM is accepting connections from debuggers.

Then, on the remote host (the debugger), we start jdb and attach it to the remote Java VM (the debuggee), and we specify the path of the source files:

jdb -sourcepath ./src/ -connect com.sun.jdi.SocketAttach:hostname=host,port=1234

Here is a screenshot of the steps:
2.1
2.2

Debugging from Eclipse

Now I will illustrate how to debug the same class remotely from Eclipse.

First, create a new Java Project in Eclipse, and import the source code of the Java class, and set the desired breakpoints:
3.1

Then, select Run > Debug Configurations.

Then, click New launch configuration, select the Project, Connection Type Standard (Socket Attach), Host, Port, Source, and click Debug:
3.3

Open the Debug perspective, and debug as usual with threads, stepping, immediate console, local variables, etc.:
3.4

Debugging Infor Grid application

Finally, I will illustrate how to debug our Infor Grid application remotely at runtime. We will need the source code of that Grid application, for example I will use the source code I wrote in part 4 of this series.

As a reminder, an Infor Grid application runs in a Grid Node, and a Grid Node is a Java VM. We will set the JDWP debugging options on that Java VM (debuggee). For that, we must change the Java command line options. Fortunately, there is a convenient node property Debug Port in the Node properties that takes care of it.

Select Infor ION Grid Management Pages > Applications > HelloWorld > Configuration:
4.0

Select Edit Properties:
4.1

Select Debug Port:
4.2

Set the application’s debug port number (specify a zero port to assign any free ephemeral port), and save the configuration changes:
4.3

Then, go to the Node Properties (Node > Advanced > Properties), ensure the debugging options were set, and take note of the port number:
4.4

Now, stop the Node, and wait until it restarts automatically, for the Java VM debug options to take effect:
4.4

Now, open the Java project with the source code in Eclipse, and set the desired breakpoints:
5.1

When you compiled the source code, verify that the Compiler Preferences included the debugging options:
5.2

Now, go to the Debug Configuration, set the port number, and click Debug:
5.2

The debugger will attach to the remote Java VM, and will show the current threads:
5.3

Now, reload the Module so we reach our breakpoints:
5.3

Finally, the debugger will reach our breakpoints, and now we can introspect the variables, step through the code, and so on:
5.4

Conclusion

That was an illustration of how to remotely debug an Infor Grid application at runtime with the Java Debugger and Eclipse. This is useful for learning, development and troubleshooting.

Note that when the Grid application threads are suspended the Node will show as status NOK_STALE, and unexpected consequences might happen in the Grid, such as timeouts or attempts to recover.

Also, remember this technique is not official and untested as we are still learning how to deal with Infor Grid applications.

 

That’s it! Please thumbs up if you like this, share around you, follow this blog, sign the petition, and author the next article.

Tagged , ,

Walking directions in a warehouse (part 2)

Today I will illustrate how I started implementing my proof-of-concept for walking directions in a warehouse, and I will provide the source code. The goal is to show the shortest path a picker would have to walk in a warehouse to complete a picking list and calculate the distance for it. This is most relevant for big warehouses and for temporary staff that are not yet familiar with a warehouse. The business benefit is to minimize picking time, reduce labor costs, increase throughput, and gather performance metrics. I used this for my demo of M3 picking lists in Google Glass.

A* search algorithm

I used Will Thimbleby’s wonderful illustration of A* shortest path in Javascript. We can drag and drop the start and stock locations to move them around and recalculate the path, and we can draw walls. I made the map bigger, and I put a warehouse image as a background.

Implementation

Here are the steps I performed:

  1. Double the map’s width/height
  2. Un-hard-code the map width/height
  3. Set the cell size and calculate the canvas width/height
  4. Un-hard-code the cell size
  5. Make a warehouse image in an image editor (I used Gimp)
  6. Add the warehouse image as background of the map
  7. Hide the heat map (search scores)
  8. Patiently draw the map, the walls, the doors, and the stock locations
  9. Save the drawing by serializing the map to JavaScript source code
  10. Replace startMap with the saved drawing
  11. Thicken the path’s stroke
  12. Hide the grid lines
  13. Hide the map
  14. Use diagonals
  15. Emphasize the path length

Here is a video of the making process (watch it in full-screen, HD, and 2x speed):

Result

You can test the result for yourself on my website here.

Here is an animated GIF of the result:
result1

Here is a video of the result for a small warehouse:

Here is a video of the result for a big warehouse:

Source code

I put the resulting HTML, JavaScript source code and images in my GitHub repository for you to download and participate.

Future work

Some of the future work includes:

  • Convert the path length into meters or feet
  • Project the geocoded stock location coordinates to the map’s coordinates
  • Set the start and end locations as input parameters
  • Automatically generate a screenshot of the path for printing alongside the picking list
  • Show the shortest path for an entire picking list using a Traveling Salesman Problem (TSP) algorithm
  • Improve performance for big maps
  • Provide a map editor to more accurately align the warehouse image with the map

Also, a much better implementation would be to use Google Maps Indoors.

 

That’s it. If you liked this, please thumbs up, leave a comment in the section below, share around you, and come author the next post with me.

Tagged , ,

M3 picking lists in Google Glass @ Inforum

I am very pleased to announce that after months of working here and there in the evenings voluntarily after work hours, I finally completed and presented both my demos of M3 picking lists in Google Glass and Augmented Reality at Inforum. They were a success. I showed the demos to about 100 persons per day during six days flawlessly with very positive reception. The goal was to show proof of concepts of wearable computers and augmented reality applied to Infor M3. My feet hurt.

Features

This is my second Glass app after the one for Khan Academy.

This Glass app has the following features:

  • It displays a picking list from Infor M3 as soon as it’s created in M3.
  • For each pick list line it shows the quantity (ALQT), item number (ITNO), item description (ITDS), and stock location (WHSL) as aisle/rack/level.
  • It displays the pick list lines as a bundle for easy grouping and finding.
  • It shows walking directions in the warehouse.
  • It has a custom menu action for the picker to mark an item as picked and to change the status of that pick list line in M3.
  • It uses the built-in text-to-speech capability of Glass to illustrate hands-free picking.
  • It’s bi-directional: from M3 to Google’s servers to push the picking list to Glass, and from Google’s servers to M3 when the picker confirms a line.
  • The images come from Infor Document Management (formerly Document Archive).
  • I developed the app in Java as an Infor Grid application.
  • I created a custom subscriber and added a subscription to Event Analytics to M3:MHPICL:U.
  • It uses the Google Mirror API for simplicity to illustrate the proof-of-concept.

I have been making the resulting source code free and open source on my GitHub repository, and I have been writing the details on this blog. I will soon post the remaining details.

Acknowledgements

I want to specially thanks Peter A Johansson of Infor GDE Demo Services for always believing in my idea, his manager Robert MacCrate for providing the servers on Infor CloudSuite, Philip Cancino formerly of Infor for helping with the functional understanding of picking lists in M3, Marie-Pascale Authié of Infor Pre-Sales for helping me setup and create picking lists in M3 and for also doing the demo at Inforum, Zack Makris of Infor Labs for providing technical support, Jonathan Amiran of Intentia Israel for helping me write the Grid application, and some people of Infor Product Development that chose to remain anonymous for helping me write a Java application for Event Hub and Document Archive. I also want to specially thank all the participants of Inforum whom saw the demo and provided feedback, and all of you readers for supporting me. And I probably missed some important contributors, thank you too. And thanks to Google X (specially Sergey Brin and Thad Starner) for believing in wearable computers and for accelerating the eyewear market.

Screenshots

Here below are the screenshots from androidcast. They show the bundle cover, the three pick list lines with the items to pick, the Confirm custom menu action, the Read aloud action, and the walking directions in the warehouse:

result0_ result1_ result2_ result3_ result3c_ result3r result4_

Vignettes

Here below are three vignettes of what the result would look like to a picker:

1 2 3

 

Inforum

Here are some photos at Inforum:

In the Manufacturing area:
20140917_162028_998

 

 

In front of the SN sign:
10704143_10152726242211873_7070689785986702196_n

 

Holding my Augmented Reality demo:
IMG_0007

Playing around with picking lists in virtual reality (Google Cardboard, Photo Spheres, and SketchFab):
bild 3

Playing around with picking lists in Android Wear (Moto 360):
20140915_110737_664_

 

That’s it! If you liked this, please thumbs up, leave a comment, subscribe to this blog, share around you, and come help me write the next blog post, I need you. Thank you!

Tagged , , , ,

Walking directions in a warehouse

Two years ago I had implemented a proof-of-concept that showed walking directions in a warehouse to complete a picking list. The idea is to visually represent what a picker has to do, and where they have to go, while calculating the minimum distance they have to walk. It will make it easier to get the job done for pickers that are not familiar with a warehouse, like temporary staff. And the business benefit is to minimize picking time, to make savings in labor costs, and to increase throughput. Also, we can save performance data on the ground, derive the gap between goals versus results, and use that as a feedback loop for continuous improvement of internal processes.

I had used my previous work on geocoding of stock locations in M3, and I had used Will Thimbleby‘s JavaScript implementation of the A* search algorithm to calculate and show the shortest path between two stock locations. I yet have to integrate the Traveling Sales Problem (TSP) algorithm for the entire picking list similar to my previous work on delivery route optimization for M3.

And there is more work to be done. For instance, the calculation responds quickly on my laptop for about 11 picking list lines, perhaps 13 with the ant colony optimization, but beyond that the calculation time grows exponentially beyond useful. Also, the calculation does not take into account bottleneck or collision avoidance for forklifts. Currently, this project is a great proof-of-concept to be further explored.

When Google Maps launched their outstanding Indoor Maps I had shelved my small project. But Google Indoor Maps requires the maps to be public which our M3 customers are reluctant to do. So for Inforum this week, I un-boxed my project and integrated it in my Google Glass demo. Here below are some screenshots of the project. I will be writing a series of posts soon on how to implement it. And I would like your feedback.

In future work, I will implement the same proof-of-concept using Google Indoor Maps.

planL

 

x y

Tagged , ,

Inforum 2014

I will be at Inforum 2014 next week. I will demo my Google Glass app with M3 picking lists. Come check it out at the M3 Labs booth in The Hub area. I will be with Marie-Pascale Authié and Peter A Johansson of Infor GDE Demo Services. My contact info is here.

Tagged , , ,

Get an image from Infor Document Archive with Java

For my project to get M3 picking lists in Google Glass, I had to learn how to retrieve in Java an image that is stored in Infor Document Archive. The technique is probably well explained and documented somewhere, but I don’t work with Document Archive so I didn’t know where to start. So as a starting point, I used one of the Java examples built-in Document Archive 10.1.x, and from there I adapted the code for the older Document Archive 10.0.x. I share my results here with you in case you too need to retrieve resources in Java from Document Archive and don’t know where to start. I will later use that code in my Infor Grid application to insert the picture of the item in the picking list in Glass.

Built-in examples

Document Archive 10.1.x is built-in with some examples in Java to connect to the server and retrieve resources. I compiled that code and it ran out of the box. I then used it as a basis to adapt the code to the older Document Archive 10.0.x for which I couldn’t find built-in examples. I will show you the code for both versions. I will also show how to encode the bytes to Base64 as I might need it later for the Google Glass Mirror API.

2

Code for Document Archive 10.1.x

Here is the Java source code for Document Archive 10.1.x:

import java.io.FileOutputStream;
import java.io.InputStream;
import com.infor.daf.icp.CMItem;
import com.infor.daf.icp.CMResource;
import com.infor.daf.icp.Connection;
import com.infor.daf.icp.SearchQueries;
import com.infor.daf.icp.SearchQuery;
import com.infor.daf.icp.Connection.AuthenticationMode;
import org.apache.commons.codec.binary.Base64;

public class Test {
	public static void main(String[] args) {
		try {
			String baseUrl = "https://hostname:26108/ca/";
			String username = "JOHNDOE";
			String password = "*******";
			String query = "/M3_ITEM_IMAGE[@M3_ITNO = \"ACME\"]";
			Connection conn = new Connection(baseUrl, username, password, AuthenticationMode.BASIC);
			conn.connect();
			CMItem item = CMItem.search(conn, new SearchQueries(new SearchQuery(query)));
			for(CMResource res : item.getResources().values()) {
				// to file
				FileOutputStream fos = new FileOutputStream(res.getFilename());
				InputStream is = res.getUrlStream();
				CMResource.streamData(is, fos, true);
				// to URL
				System.out.println(res.getUrl().toString());
				// to Base64
				byte[] bytes = CMResource.createByteArray(res.getUrlStream());
				System.out.println(new String(Base64.encodeBase64(bytes)));
			}
			conn.disconnect();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
}

Find the Java library for Document Archive 10.1.x, icp.jar, and the required open source libraries httpclient, httpcore, commons-logging, commons-codec, and jaxen:

<LifeCycle>\<host>\grid\<grid>\grids\<grid>\applications\DocumentArchiveCM\lib\

3

Compile and run the code with:

javac -extdirs . Test.java
java -cp icp.jar;httpclient-4.3.2.jar;httpcore-4.3.1.jar;commons-logging-1.1.1.jar;commons-codec-1.6.jar;jaxen.jar;. Test

The application will connect to Document Archive, will search the image by query, will retrieve the resource and will save it to a file, for example to JPEG.

The application will also show the URL to the resource, for example:

https://hostname:26108/ca/api/resources/93+3+ICM8+icmnlsdb13+M3_ITEM_IMAGE59+26+A1001001A14F13A20952E6009918+A14F13A20952E600991+14+1027?$token=aHR0cDov&#8230;

The application will also show the Base64-encoded bytes of the resource.

Code for Document Archive 10.0.x

Here is the Java source code for the older Document Archive 10.0.x. It is very similar to the newer code above, the package names are different (intentia instead of infor) and some methods are older. I had to decompile icp.jar to learn and adapt the code.

import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Iterator;
import org.apache.commons.codec.binary.Base64;
import com.intentia.icp.common.CMItem;
import com.intentia.icp.common.CMResource;
import com.intentia.icp.common.Connection;

public class Test {
	public static void main(String[] args) {
		try {
			String baseUrl = "https://hostname:25194/ca/";
			String username = "JOHNDOE";
			String password = "*******";
			String query = "/ESA_ItemImage[@ESA_ItemNumber = \"ACME\"]";
			Connection conn = new Connection(baseUrl, username, password);
			conn.setAuthMode(Connection.BASIC);
			conn.connect();
			CMItem item = CMItem.search(conn, query);
			Iterator it = item.getResources().iterator();
			while (it.hasNext()) {
				CMResource res = (CMResource)it.next();
				// to XML
				System.out.println(res);
				// to file
				if (res.getEntityName().equals("ICMBASE")) {
					InputStream is = res.retrieveResource(conn);
					FileOutputStream fos = new FileOutputStream(res.getOrgFileName());
					CMResource.streamData(is, fos);
					// to Base64
					byte[] bytes = CMResource.createByteArray(res.retrieveResource(conn));
					System.out.println(new String(Base64.encodeBase64(bytes)));
				}
			}
			conn.disconnect();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
}

Find the Java library for Document Archive 10.0.x, icp.jar, and the required open source libraries httpclient, httpcore, commons-logging, commons-codec, jaxen, and commons-io:

<LifeCycle>\<host>\grid\<grid>\grids\<grid>\applications\DocumentArchiveCM\lib\

3

Compile and run the code with:

javac -extdirs . Test.java
java -cp icp.jar;jaxen-1.1.1.jar;httpclient-4.2.2.jar;httpcore-4.2.2.jar;commons-io-2.4.jar;commons-logging-1.1.1.jar;commons-codec-1.7.jar;. Test

The application will connect to Document Archive, will search the image by query, will retrieve the resource and will save it to a file, for example to JPEG.

The application will also show the XML of the resource, for example:

<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<res>
    <pid>85 3 ICM8 icmnlsdb7 ICMBASE58 26 A1001001A14F20A45344I4341718 A14F20A45344I434171 13 300</pid>
    <id>A1001001A14F20A45344I43417</id>
    <compId>A14F20A45344I43417</compId>
    <version>1</version>
    <entityName>ICMBASE</entityName>
    <type>0</type>
    <acl>
        <name>defaultACL</name>
    </acl>
</res>

The application will also show the Base64-encoded bytes of the resource.

 

That’s it. If you liked this, please click Like, leave me your thoughts in the comments below, and share your solutions by writing posts.

Also, please join the campaign and sign the petition to Infor so they make more of their source code available such that we can all learn more and make better solutions.

 

Thank you.

 

Tagged ,

Hacking Infor Grid application development (part 5)

Here is the fifth part in the series Hacking Infor Grid application development. This time I will show you how to deploy a web application archive, WAR file. It is trivial and quick as the Infor Grid automatically deploys it.

Create the archive

Simply ZIP the contents of the web application into a WAR file:
1

File & folder structure

Move the WAR file into the webapps folder of the Grid application, and delete the rest of the webapps content (WEB-INF, JSP, etc.) so that there is only the WAR file left:

[...]
|
\---webapps
        HelloWorld.war

Deploy

Create the Grid application archive GAR and deploy it in the Grid as usual. The Infor Grid will automatically deploy the WAR file under webapps:
2

GitHub

I updated the GitHub repository with a Tag for part5.

Petition

Remember to join the campaign in asking Infor Product Development to release their Grid Development Tools and tutorials and to make their source code available so we can learn how to make good Grid applications.

Meanwhile, remember this is a hack with the intention to learn and progress.

Tagged , ,

Hacking Infor Grid application development (part 4)

Continuing the series Hacking Infor Grid application development, today I will show: how to decompile Java applications, how to write to the Grid application log files, how to read Grid application properties, how to secure the Java web application, and how to start playing with the HelloWorld app on GitHub. Remember this is currently a hack, it is at your own risk, there are limitations as discussed on part 1, and please join the campaign and sign the petition to Infor Product Development for making their source code available. The intention is to learn the internals of the applications we use every day, push their limits, and develop great software.

Decompile Java applications

First of all, check your licenses to determine if you are legally allowed to decompile the Java application you have in mind.

For this series I decompiled the Infor Grid core grid-core-1.11.27.jar to understand how to write to the Grid application log files and how to get Grid application properties. I also often decompile applications like M3_UI_Adapter (MNE), Event Hub, M3 Web Services, and Infor Process Automation to understand how they work, make enhancements, troubleshoot, and find bugs. All the JAR files are located in LifeCycle Manager at E:\Infor\LifeCycle\<host>\grid\<grid>\grids\<grid>\applications\. It is already common practice to decompile Infor Smart Office with RedGate Reflector (C#) to push the limits of Smart Office scripts and Smart Office SDK applications. I wish the source code of all applications were available.

For decompiling Java applications, I use the great Java Decompiler and its GUI. I simply drag and drop a JAR file and it automatically decompiles all files recursively:
1

Write to Grid application log files

To write to the Grid application log files, get the logger and log at the information, warning, error, debug, or trace levels:

import com.lawson.grid.util.logging.GridLogger;
[...]
private static final GridLogger log = GridLogger.getLogger(HelloWorld.class);
[...]
log.info("Yay, I'm writing to the log file :)");
log.warn("Hey, it feels hot in here!");
log.error("Ouch, that hurt :(");
log.debug("Useful data 48656C6C6F576F726C64");
log.trace("Wooohooo 01001000 01100101 01101100 01101100 01101111 00100000 01010111 01101111 01110010 01101100 01100100 00100001");

Set the log levels accordingly:

Check the result in the Grid application log file:
3

The log files are also directly in the log folder for use with a tail program or so:
5

Read Grid application properties

Declare Grid application properties in the application deployment descriptor GRID-INF\application.xml:

<property name="message">Hello Wrrrld!</property>

6

Then, read the properties with:

import com.lawson.grid.node.properties.GridProperties;
[...]
GridProperties p = ModuleContext.getCurrent().getProperties();
String message = p.getProperty("message");
log.info("The message is: " + message);

Re-deploy the application and check the application properties:
7

And here is the result:
4

Secure Java web application

To secure the Java web application in WEB-INF\web.xml:

<security-constraint>
    <web-resource-collection>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>grid-user</role-name>
    </auth-constraint>
</security-constraint>

Set the User and Role Mappings in the Grid Configuration Manager accordingly:8

Restart the application.

The Grid will now challenge for authentication:
9

HelloWorld app on GitHub

I published the HelloWorld Grid application source code on my GitHub repository so you can play along, learn, and contribute your code, and I added tags – part1, part2, part3, and part4 – so you can download the source code that corresponds to the desired part in this series:
10

Summary

That was an illustration of how to decompile Java applications, how to write to the Grid application log files, read Grid application properties, secure the Java web application, and start playing with the HelloWorld app on GitHub. Remember to play responsibly, know the limitations, sign the petition, and contribute your findings to the community.

That’s it! If you liked this, please click Like, write your comments, click Follow to subscribe to the blog, share around you, and author your own ideas. Thank you.

Tagged , ,

Hacking Infor Grid application development (part 3)

In the series Hacking Infor Grid application development, today I will illustrate how to add a JAR file to an Infor Grid application and a JAR file to a dynamic web application in that Grid application (which is trivial).

JAR for Grid application

First, create a simple Java library:

package net.company.your.library1;

public class HelloWorldLibrary1 {
	public static String getMessage() {
		return "Hello World sample library for my Grid application";
	}
}

Then, compile it with:

javac net\company\your\library1\HelloWorldLibrary1.java

Then, add it to a JAR file with:

jar cvf HelloWorldLibrary1.jar net\company\your\library\HelloWorldLibrary1.class

Then, call that library from the Grid application with:

[...]

import net.company.your.library1.*;

public class HelloWorld implements ApplicationEntryPointEx {

	public boolean startModule(ModuleContext paramModuleContext) {
		System.out.println(HelloWorldLibrary1.getMessage());
		return true;
	}

	[...]
}

Then, recompile that Grid application as usual with:

javac -cp grid-core-1.11.27.jar;. net\company\your\HelloWorld.java

Here’s the result in the command prompt:
1.1

Then, create a jars folder in the Grid application and add the JAR file to it:
1.3

The default folder for JAR files is jars. It seems other Infor Grid applications use folder lib instead. We can change the classpath in the Grid application’s properties, for instance the application M3UIAdapter has JAR files in a folder lib:
3.2b

Then, replace the Grid application:
1.2

Then, restart the Module in the Grid Management Pages:
b4

We can see the result in the logs:
1.4

JAR for dynamic web application

Now let’s create a second Java library for the dynamic web application of the Grid application; this is classic J2EE and trivial:

package net.company.your.library2;

public class HelloWorldLibrary2 {
	public static String getMessage() {
		return "Hello World sample library for my dynamic web application";
	}
}

Then, compile it and add it to a JAR file as shown above.

Then, let’s use that library from the servlet (or from a JSP):

[...]

import net.company.your.library2.*;

public class HelloWorldServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		[...]
		out.println(HelloWorldLibrary2.getMessage());
	}
}

Then, recompile the servlet as usual.

Here’s the result in the command prompt:
2.1

Then, create a lib folder in the WEB-INF folder of the dynamic web application:
2.3

Then, replace the servlet (or JSP):
2.2

And refresh the servlet (or JSP) to see the result:
2.4

Summary

That was how to add a JAR file to an Infor Grid application and a JAR file to a dynamic web application in that Grid application (which was trivial). Next time I will find out how to add a WAR file.

Also, remember this is a hack that currently has limitations due to our lack of knowledge of how to develop good applications for the Infor Grid, as discussed in part 1 of this series.

Also, remember to join the campaign and sign the petition to Infor Product Development for making their source code available.

That’s it! If you like this, please click the Like button, leave a comment below, subscribe to this blog, share around you, and write about your own ideas here. Thank you.

Tagged , ,
Follow

Get every new post delivered to your Inbox.

Join 146 other followers