Blog Posts

Statistics: Blogs: 33 Blog Posts: 238   1 2 3 4 ... 16 Previous Next
Items per page
0

In EGL CE you are able to debug both the Rich UI front-ends, as well as the Service back-ends. All debug sessions must begin with the Rich UI application. There are several ways to initiate a debug session, such as right-clicking a RUIHandler file and selecting Debug EGL Rich UI Application:

http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/38-1271-1763/blog1.png

Or if you have the editor open, switch to the Preview tab and click on the Debug icon:

http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/38-1271-1771/blog2.png

Once your debug session begins, the Rich UI application will be loaded in an external Web browser. Your default system Web browser will be used, but this can be changed in Window > Preferences > General > Web Browser.

Another preference page worth mentioning is EGL > Debug. The EGL CE help system has detailed descriptions about the debugger preferences, as well as which preferences apply to Services and which apply to RUIHandler parts.

If you're not familiar with developing in Eclipse, breakpoints can be added to your EGL source files by double-clicking inside the left margin of the source editor. If a breakpoint marker doesn't appear, that means it's not a valid location for a breakpoint. You can also right-click inside the left margin to add/remove/disable breakpoints.

As an example, let's use the ServiceDemo.egl sample, inside project com.ibm.egl.rui.samples.ce. Place a breakpoint at line 59, which is the first line of function sayHello. Now start the debug session for this handler. After the page is loaded in the external browser, enter your name and click the Say Hello button; the EGL CE workbench should be activated and you'll be prompted to switch to the Debug perspective. Click OK, optionally checking the box to automatically take this action in the future, and you should see the following:

blog3.png

I have highlight two sections in the screenshot above.

Section 1: The Debug view contains the debug stack, which is the stack of funtions currently being executed, and is only visible when you're suspended. The toolbar in this view can be used for the typical debugging commands: step into, step over, step return, resume, terminate, and suspend.

Tip: If you accidentally coded an infinite loop, or something is taking an incredibly long time to execute and you're curious why, you can click on the suspend button blog8.png to pause the debugger. If no code is currently running when you click suspend (e.g. browser is waiting for a user event), then the debugger will immediately pause the next time any of your code is run.

Section 2: The Variables view will display all the variables currently in scope. The variables have been divided into two sections: Global variables ("ServiceDemo" in the screenshot) and local variables ("sayHello" in the screenshot); these will be the name of the main part and the name of the function, respectively.

The Breakpoints view displays all the breakpoints in your workspace. One thing worth noting is you can disable breakpoints without deleting them, and there's also a "Skip all breakpoints" option that you might find quite useful.

Tip: Hover the mouse over a variable that's in scope while suspended, and you'll get a tooltip containing its value:


http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/38-1271-1772/blog4.png


Picking up where we left off in our example, click on the resume button http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/38-1271-1767/blog5.png to continue execution. You'll be presented with a popup dialog; this dialog is presented when a Service invocation via an Interface part is encountered.

http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/38-1271-1768/blog6.png

If you have the source code for the target service in your workspace, and you want to be able to step through its code, specify "Use source code", otherwise specify "Use deployed version". If you are invoking a deployed service, then you will need to make sure your EGL deployment descriptor contains a Service client binding which provides information on how to reach the Service. If you don't want to be prompted again for this binding key in the future, you can check the box to save your decision.

Now would be a good time to set a breakpoint in the Service part. Put a breakpoint on line 18 in SayHelloService.egl, which is the first and only line of function hello. Click OK and you should be suspended inside the Service, which runs as a separate process. Click on the resume icon like before and the Service will complete, returining a string back to the Rich UI client.

Tip: You can step into a Service invocation just like you would step into a function. This will kick off the service and immediately continue to the next line of the Rich UI code. The Rich UI code can be run in parallel with the Service code, since they are in separate processes, and the Service callback function (or error function) will be run once the Service completes and the Rich UI function stack is empty.

After the Service has returned data to the client, switch back to your browser to see the results:

http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/38-1271-1769/blog7.png

Feel free to login and add a comment or question about the debugger.

Justin

0 Comments Permalink
2

This is my first post on our C/C++ Cafe that has been long in coming.

If you are like me, then you are a new zOS programmer. The learning ride has been quite turbulent and there are ways to go yet. If you are a devoted programmer then you feel quiet excitement of your new program almost working, tempered by the chance of another large manual being 'thrown' at you. zOS is one of those products that has too much of a good thing, that is there is a LOT of documentation. This fact very quickly becomes an advantage as one gains more experience.

No matter what design patterns you use, almost as soon as you start writing code, you will need to include other files, be it either your own include files or third party libraries. For efficiency purposes, these files will in all likelihood reside in datasets. To make things more interesting, the documentation might instruct to use directory based (HFS) #include, confusing the new-comers as to where files reside.

I want to discuss two tasks that come up when dealing with include files:

  • Finding the include files
  • Dealing with preprocessor macros

If the compiler already found the include file (i.e. successful
compile) and you are interested where the file is located (i.e. which version of the library you are actually using), both -qlist and
-qsource produce an includes section.

#Will list all included files:
xlc -qsource -c foo.c | sed -n '/I N C L U D E S/,/E N D O F I N C L U D E S/ p'
#Will list the path to NAME_OF_INCLUDE:
xlc -qlist -c foo.c | grep NAME_OF_INCLUDE

The grep command might not return anything because of some zOS specific file translations, hence be careful:

  • if NAME.OF.INCLUDE contains dots, the real file name might be translated to INCLUDE.OF.NAME or just NAME
  • if NAME_OF_INCLUDE contains underscores, it might get translated to NAME@OF@INCLUDE

If you are using V1R11 compiler, there is a new feature, -qmakedep (on USS only) that will produce a list of all included files. It is much easier to remember then the sed command above. For example if you compiled:

# previus invocation: 'xlc -c foo.c'
# Append -qmakedep
xlc -c foo.c -qmakedep
cat foo.u

For previous releases of zOS compiler, have a look at the makedepend utility. It contains some other options that might be useful for include file debugging.

-qshowinc is another particularly useful option, if you already have the include files. It shows the the contents of the included files. It is similar to what PPONLY (-E equivalent) option does, except it outputs to the listing and does not strip preprosessor directives. However, be ready to pipe the output to other programs to filter out the thousands of lines of code produced. Most of the time I use less and its search features. sed and grep sometimes are also be useful.

If you are trying to include a file, and the compiler cannot find it, there is more research involved. In a general case, the include files can be found, top to bottom in these places:

pwd
LSEARCH
DD:USERLIB
SEARCH
DD:SYSLIB


  • System includes can only be found in SEARCH and DD:SYSLIB.
  • DD: statements come from the JCL, hence you might need to know how the compiler was invoked.
  • SEARCH and LSEARCH come from the compiler options hence are easy to modify

SEARCH and LSEARCH both contain a list of directories and partial dataset qualifiers. The topic is discussed in detail in our Compiler User Guide in 'Chapter 7: Using include files'. I personally found the flowcharts in Chapter 7 and the Examples in the LSEARCH option explanation cleared up most of the most dataset questions that I had. It is worth noting for newcomers that terms 'z/OS Unix files' and 'HFS files' are equivalent and refer to directory based files (i.e. similar to organization Linux and Windows file systems) (as opposed to DATASETs that can be sequential or PDS in this discussion)

-qlist, -qsource options and -V and -v c89 and xlc flags provide a quick way to find out what the values of LSEARCH and SEARCH are.

As Visda has discussed before in her blog post, NOSEARCH() and NOLSEARCH() reset the respective option value back to empty.

Last topic I wanted to touch was preprocessor macros and what options are available when dealing with them.

Michael Wong has posted here a way to find compiler predefined macros on AIX using the SHOWMACROS option. zOS unfortunately does not have this option till V1R11. The best equivalent is to use the makedepend utility -Wm,list option and then view depend.lst. It will contain a list of predefined compiler macros. However, makedepend utility is being deprecated since V1R11 in preference to built-in -qmakedep option.

Nevertheless most macros should be mentioned in the zOS manuals related feature sections. Here is a small list from the manual.

If you already have the macro name you wish to use, have a look at the -qEXPMAC option. This option will show you the value of the macro in the source listing. It is most useful when combined with -qshowinc.

I hope this gets you started on the right track.

2 Comments Permalink
0

There is a new entry under Resource Library you should be aware of. The HATS Samples and Snippets section is now kicked off with a very modern-looking HATS template that you can use in your projects.

Check it out.

0 Comments Permalink
4

While you are developing your EGL project, you can run it using the Preview tab and using the debugging tools. You can even try out services that you have written or ones from third parties. Testing your application this way saves a lot of time and effort over other development tools that require you to deploy to confirm any changes behave as you expect.

When you are satisfied with your application, you can deploy it to a Web application server such as Apache Tomcat version 6. EGL projects aren't directly deployed to an application server; EGL projects are deployed as dynamic Web projects. EGL source code is generated as Java and JavaScript in the Web project.

http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/38-1268-1747/deploy.gif
To create your target Web project, open the deployment descriptor file (.egldd) located in the EGLSource directory of your EGL project. The deployment descriptor specifies where to deploy - the target Web project (including the target runtime server), and what to deploy - the Rich UI handlers and services.

http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/38-1268-1750/Deploydescriptor.JPG
In the deployment descriptor editor, click New next to the Target name field to open the New Dynamic Web project wizard. Enter the name of your Web project. Select Apache Tomcat v6.0 as the target runtime. If you haven't created a server, you can click New next to the Target runtime field, which opens the New Server Runtime Environment wizard. Select Apache Tomcat v6.0 from the list of servers and click Next. If you have Tomcat installed, you can browse to the installation directory. If you don't have Tomcat installed, you can click Download and Install, accept the license agreement, and click OK. (Note: watch the lower right-hand corner of the workbench for progress. If for some reason you get an error, I recommend going to the Apache site and downloading and installing Tomcat then just point to it.)

After you enter the target Web project, you can specify what to deploy. By default, all Rich UI handlers are listed to deploy, meaning each handler generates an HTML file for each locale specified. If you don't want an HTML endpoint created for a particular handler, since you might not want users to be able to go directly to that URL, click the Rich UI Deployment tab and select which handlers you want to deploy. If you have EGL services that you want to expose as Web services, add them under the Services Deployment tab. We have more on services in a later blog post.

When you finish editing the deployment descriptor, save it. To deploy to the target Web project, click the Deploy the EGL descriptor icon on the top right of the editor window or right-click on the .egldd file and select Deploy EGL descriptor from the menu.

You can view the results in the EGL Deploy Results tab near the bottom of your workspace. Your target Web project should contain JavaScript and Java generated from your source EGL project. For instance, if your EGL project had a Rich UI handler that you selected to deploy, you should see a corresponding HTML file in the WebContent folder. To see the application in action, right-click on the HTML file, select Run As>Run on Server, and select Tomcat 6. The server will start and the file should open running on localhost (or the hostname you specified).

http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/38-1268-1751/RunAs.JPG

Deployment descriptors let you customize the deployment of your EGL applications. You can create more than one deployment descriptor for each EGL project. For instance, you may want to specify a Web project to deploy your Rich UI handlers and a second one to deploy your services. Each descriptor can be deployed individually (using the Deploy EGL descriptor option) or all at once by right-clicking on the EGL project name and selecting Deploy EGL project.

We hope this helps you understand some of the basics of deploying EGL projects to the Web. We would love to see your EGL applications out there!

Theresa

4 Comments Permalink
0

Integration objects play an important role in managing the state of an application or creating a new host connection. However, they typically are used for starting a new HATS connection from within an existing HATS customization. So when should you use an integration object? Web services and combining multiple hosts data onto a single screen are the two options of choice.

Integration objects are essentially a Java wrapper the encapsulates the macro state management. What I mean by that is, you can call setters and getters on the integration object and manage its state.

Macros on the other hand can only be run within the context of either a customization or the macros tab of the default connection. So in case you didn't already know, you can run macros automatically when the connection is established.

So, think of integration objects as an extension to a macro. They still use the .hma script during execution and they given greater flexibility for use in web services or they allow you to create a nice lightweight framework for use with JSF, Richfaces, Spring, Hibernate, and other exciting technologies.

Greg Peters
Solutions Specialist
Sirius Computer Solutions

0 Comments Permalink
10

I have posted a video walkthrough demonstrating how to call an RPG program using EGL Community Edition. The video is available here. (Make sure you watch in full-screen, HD mode.)

Using this video you can learn:

  • Setup steps required to call RPG from EGL/CE
  • Construction of a service to call the RPG program
  • Construction of a Rich UI to invoke the service
  • Debugging client and service code

I welcome your questions and feedback.

10 Comments Permalink
2

Today, I wrote a game in EGL Rich UI inspired by the well-known web game called "Escape", "Escapa", "The Red Box Game", or whatever name the latest inspired copier decided to give before hosting it on their own homepage. I am still trying to find out who really wrote the original.

Anyway, it looks like this:

escape.jpg
See http://eglplanner.com/escape

The intent of the game is simple. You drag the red box labelled "EGL" around with your mouse. All you need to do is avoid the blue boxes and the walls.

How does the game work?

The game essentially consists of two parts: the UI that draws the boxes and let you drag the red box and a service component that can show the top 10 scores. I will describe the two parts in more detail now.

How to avoid Java, C, PHP, and JavaScript

The main algorithm for this game is the following:
  • place a red box in the middle and allow the user to drag it
  • place four blue boxes elsewhere and give each a unique motion vector
  • start a new job to run each X milliseconds to move each blue box
  • when the red box goes outside the white box or overlaps with a blue box, stop
  • every 10 seconds decrease the value of X so the blue boxes will move faster

The blue boxes shown in the UI are positioned absolutely using a syntax like this:
    new Div {
        position = "absolute", x = 300, y = 330, 
        width = 100, height = 20, 
        color = "white", background = "navy", font = "Arial", 
        innerHTML = "<center style='margin-top: 1px'>JavaScript</center>"        
    }


By making the boxes positioned absolutely, we can place them at any place we want. For this box, the initial location is at x=300 and y=330.

Each time the game timer goes off, we move the blue boxes in a given direction:
    moveEnemy(enemies[2], -12, -20);


For each blue box, we remember its x and y direction. For instance, when it bounces against the right wall, we make its x direction -1. The box is moved simply by giving it a new x and y coordinate. After moving the box, we check to see if we now touch the red box. If so, we stop the game.
    function moveEnemy(enemy Div, x int in, y int in)
        directionX int = enemy.getAttribute("directionX");
        directionY int = enemy.getAttribute("directionY");
        if (touchesVerticalWall(enemy))
            directionX *= -1;
            enemy.setAttribute("directionX", directionX);
        end
        if (touchesHorizontalWall(enemy))
            directionY *= -1;
            enemy.setAttribute("directionY", directionY);
        end
        enemy.x += x * directionX;
        enemy.y += y * directionY;
        if (enemyTouches(enemy))
            stop("a blue box");
        end
    end


The red box itself has drag and drop handlers define on it:
    red Div {
        onStartDrag = startDrag, onDrag = drag, onDropOnTarget = endDrag, 
        cursor = "pointer", 
        position = "absolute", x= 205, y = 205,    width = 40, height = 40, 
        background = "darkred", color = "white", font = "Arial",
        innerHTML = "<center style='margin-top: 9px'>EGL</center>"
    };    


This allows us to start the game and drag the red box while the user moves the mouse:
    function startDrag(widget Widget in, x int in, y int in) returns(boolean)
        dx = x - red.x;
        dy = y - red.y;
        start();
        return (true);
    end
    function drag(widget Widget in, target Widget in, x int in, y int in)
        if (!stopped)
            red.x = x - dx;
            red.y = y - dy;
        end
        if (outsidewhite())
            stop("the black border");
        end
    end
    function endDrag(widget Widget in, target Widget in, x int in, y int in)
    end


Finally, when the game stops, we inform the user and display the top 10 scores:
    function stop(reason String in)
        message.text = "You touched "+reason+". Drag the red box to start.";        
        reset();
        stopped = true;
        top10.score = (browser.currentTimeMillis() - startTime)/1000;
    end


Keeping a Top 10 List

Our top 10 list consists of a little bit of UI, and a service call to report the current score and receive an answer back with the total number of games played and the top 10 games.

The UI is nothing thrilling, other than using a cookie to remember your name:
    nameLabel TextLabel { text = "Your Name: " };
    cookie Cookie { key = "name" };
    nameField TextField { width = 80, text = cookie.value, onKeyUp ::= setName };


That same cookie is updated when the user enters a new name, and stored in the browser's cookie jar. Next time the user returns, the stored value will be automatically picked up. Updating a cookie value is as easy as giving it a new value:
    function setName(e Event in)
        if (nameField.text != "")
            cookie.value = nameField.text;
        end
    end 


The service calls a REST service with 2 URL parameters. It returns a record with inside it an array of top scores. Notice from the definition below that it is not relevant if the service is using XML or JSON to encode its contents. The EGL runtime will determine at runtime how to parse the result.

The service definition looks like this:
    interface HighScores
        function getTop10(name String in, score float in) returns(HighScoresRecord) 
           {@GetRest {
                   uriTemplate="http://eglplanner.com/escape/highscore.php?name={name}&score={score}"
           }};
    end    
    record Result
        total int;
        top10 ScoreRecord[0];
    end
    record Score
        name String;
        value float;
    end


To call the service, we use the EGL call statement identifying the service we want to call and what function we want to use when the response arrives in the future:
    function setScore(score float in)
        this.score = score;
        scoreField.text = "Score: "+score;
        call svc.getTop10(nameField.text, score) returning to handleTop10 onException ServiceLib.serviceExceptionHandler;
    end


The top 10 scores are stored in a div that is given an opacity of 0.8, so it is a little bit transparent:
    top10 Div { 
        position = "absolute", x = -100, y = 5, 
        *opacity = 0.8*, padding = 10, background = "black", 
        borderColor = "red", borderWidth = 12, borderStyle = "solid" 
    };


When the answer comes back from the top10 service it is converted automatically by EGL into a set of nested records and we simply add them to our top10 div. Finally, we show the top10 div in the right position:
    function handleTop10(result HighScoresRecord in)
        s String = "Total plays: <b>"+result.total + "</b>. " +
            "Your score: <b>"+score+"s</b>.<p>" +
            "Here are the Top 10 scores:

" + "<table border=1 width=300 cellpadding=3 style:'margin:10px; opacity: 1.0'>"; for (n int from 1 to result.top10.getSize()) score ScoreRecord = result.top10[n]; s += "<tr><td>" + n + "</td><td>" + score.value + "s</td><td>   " + score.name + "</td></tr>"; end s += "</table>"; top10.innerHTML = s; top10.x = scoreField.x + scoreField.pixelWidth + 15; ui.table.setAttribute("valign", "top"); showTop10(true); end function showTop10(value boolean in) if (value) ui.appendChild(top10); else ui.removeChild(top10); end end



Using PHP to implement the backend service

All the client code is done in EGL. I decided to place the game on an ISP where I took the cheapest plan available. The plan comes standard with PHP and MySQL. So, I decided to try and use MySQL and PHP to store the high scores to see how that worked.

The MySQL table structure is pretty simple:
    name    varchar(64)           
    score    float          
    ip        varchar(32)


I added and IP field to remember where the service came from (which is of course a very limited approach to authentication). I created the table using the phpMyAdmin client that my Internet provider offers.

Then I wrote some PHP and placed it right next to my game's index.html file. Here is what the (insecure) PHP looks like:
<?
   $host = "localhost";
   $user = "*********";
   $pass = "*********";
   $db      = "highscores";

   $name = $_REQUEST['name'];
   $score = $_REQUEST['score'];
   $ip = $_SERVER['REMOTE_ADDR'];

   $connection = mysql_connect($host, $user, $pass) or die ("Unable to connect!");
   mysql_select_db($db) or die ("Cannot open database $db");
 
   if (isset($name) && isset($score)) {      
      $query = "INSERT INTO highscores(name, score, ip) VALUES('$name', '$score', '$ip')";
      $result = mysql_query($query);
   }

   $query = "SELECT * FROM highscores";
   $result = mysql_query($query);
   $total = mysql_num_rows($result);
   $query = "SELECT * FROM highscores ORDER BY score + 0 DESC LIMIT 10";
   $result = mysql_query($query);
   echo "<result><total>$total</total>";
   if (mysql_num_rows($result) > 0) {
      while($row = mysql_fetch_row($result)) {
         echo "<score><name>$row[0]</name><value>$row[1]</value></score>";
      }
   } 
   echo "</result>";
   mysql_close($connection);
?>


Security

My PHP code is highly insecure for various reasons. First, anyone can simply call the URL above and assign any score they like:

Hack your own score

Note that I added some sanity checks so that the above URL no longer works :-)

Using a REST service with URL parameters makes it trivial to call in a browser. Tools like Rational AppScan know this and run a huge number of "worst practice" scenarios on a website to find holes like the one I inserted here.

Some ways of making service hacking more difficult would be:
  • Use a POST and place the arguments in the message body, instead of on the URL.
  • Use some "secret" encoding for the message that only the client and the service know about.
When you use SOAP messages, you already use POST and a secret encoding (in this case a SOAP envelope).

One complicating problem is that our client is written in easy to read JavaScript (compiled from our EGL). That gives hackers a lot of leverage. However, even extreme obfuscation of the JavaScript won't help as hackers can easily use Firebug in Firefox to watch the network traffic and derive what services are used and how to call them. Then they can play the man-in-the-middle game to make the server believe they are the client.

Maybe JavaScript obfuscation combined with service obfuscation has a higher degree of chance of making hackers give up and look for an easier target to hack.

Of course, obscuring thing stops the really silly hacks and even the accidental ones. However, as Andy Tanenbaum used to say when I was stil back in school attending his class on Operating Systems: obscurity is the worst form of security.

Always use SLL and proper authentication to increase security.

Securing the channel and authentication helps to a certain degree. In the end, however, services have to be extremely defensive, paranoid, trace everything, apply statistical analysis, and allow for easy human intervention. Think of your credit card company calling you on your cellphone to verify a suspicious transaction. Also, most comment sections on website have a button to report spam messages or abuse. Any system that runs over the Internet should be assuming the worst and be able to easily recover from abuse.

SQL Injection

One special form of disruptive hacking is to try and make the service run arbitrary code on the hacker's behalf. In our PHP example shown above, we allow for SQL injection very easily.

Then main attack vector in our example is given here:
   $name = $_REQUEST['name'];
   $score = $_REQUEST['score'];
   ...      
   $query = "INSERT INTO highscores(name, score, ip) VALUES('$name', '$score', '$ip')";


We retrieve $name and $score from the request URL, and compose a query out of it. If we pass in 'name=Chris' and 'score=32.351', the resulting query would be:
    INSERT INTO highscores(name, score, ip) VALUES('Chris', '32.351', '192.168.0.1')";


Now, assume someone passes the following parameters to the REST service:
    name=x',1,foo); DROP TABLE highscores; --


Our query would then look like this:
    INSERT INTO highscores(name, score, ip) VALUES('x',1,foo); DROP TABLE highscores; --', '32.351', '192.168.0.1')";


As "--" starts a comment in SQL, the query now becomes the following two separate SQL statements:
    INSERT INTO highscores(name, score, ip) VALUES('x',1,foo); 
    DROP TABLE highscores; 


By naively allowing any arguments to be passed to us we allowed random SQL code to be executed on our database. Hackers do not need access to the PHP to come up with this, as automated tools are available to try random fragments until they find one that works.

The simplest solution is to not allow for the script to insert the ';' character. Namely, without that the SQL injection cannot insert a second statement. To avoid further unintentional modifications to the original select statement, we can also check for the single quote character.

To help fight SQL injection, there is a simple PHP trick to sanitize URL parameters. It looks like this:
   $name = mysql_real_escape_string($_REQUEST['name']);
   $score = mysql_real_escape_string($_REQUEST['score']);


I added that to the PHP that is currently used by the published game.

Monitoring

In our sample above, we do not monitor client access, other than storing the IP address. Additional information may be collected and stored, such as host name, referer page, browser agent, timestamp, etc. Basically, you should record anything that may help the FBI solve your case once someone drained your server from all its data.

How to really solve security problems

Basically the advise is: Don't try this at home, kids!

Enterprise organizations should not use adhoc security models, of course. The recommendation is to use something like Tivoli Access Manager to control access to, and monitor, their services.

Furthermore, instead of using PHP, you should really write your services in EGL, compile them to Java, and run them on WebSphere, which is proven to be much more secure for Enterprise applications. Using EGL will also make it easier for you to write the service as you will not have to struggle with the quirky syntax of both PHP and MySQL.

Download

To take a look at the client code yourself, download the following attachment and import it as an existing project into your workspace.

Attachment: escape.zip

2 Comments Permalink
9

Why Portals?

One of the most inspiring video games I have ever seen is the Aperture Science Enrichment Center, also known as Portal. It bends the law of physics in very interesting patterns:

http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/1735/portal.jpg
Image/article source: Wired Magazine

Now, I am kind of tricking you, as this is not the kind of Portal this blog entry will discuss. However, I cannot help thinking of this game whenever someone asks me if you can do "portals" in EGL Rich UI.

So seriously, when people ask me about Portals there are asking two different questions:

  1. How can I write an EGL Rich UI application and use it inside a WebSphere Portal? In essence a Rich UI application is really an HTML file with some JavaScript embedded inside it. That can be produced by a JSR 286 portlet. We may have time to dive deeper into that in a future blog. What I really want to discuss is the next question...

  1. How can I write a Rich UI application that has a main Rich UI handler and that downloads other RUI handlers on demand and make them appear as being a integral component of the larger application. In other words, how can I make a client-side Portal? That question is really the topic of this blog entry.

How to build a client-side Portal?

Our starting point is the GadgetContainer sample that comes with EGL CE and that can be found in the Dojo samples project that EGL CE automatically creates for you:

http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/1736/GadgetContainer.jpg
First step is to reduce that sample to something a bit simpler, and then use other applications (preferably done in EGL Rich UI) to occupy the various portlets.

Here is our most reduced version of our Portal:

Handler Portal Type RUIHandler{ initialUI = [ ui ] }    
    ui GadgetContainer { columns = 2, columnWidth = 150, gadgets = [
        new Gadget { title = "Portlet1", column = 1, children = [] },
        new Gadget { title = "Portlet2", column = 2, children = [] },
        new Gadget { title = "Portlet3", column = 1, children = [] },
        new Gadget { title = "Portlet4", column = 2, children = [] }
    ]};
end


This produces a portal with 4 empty portlets:

http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/38-1264-1737/portal1.jpg
Now, we will place an iframe into one of the portlets and insert another EGL Rich UI application inside it:

Handler Portal Type RUIHandler{ initialUI = [ ui ] }    
    ui GadgetContainer { columns = 2, columnWidth = 150, gadgets = [
        new Gadget { title = "Portlet1", column = 1, children = [
            new IFrame {
                width = 135, height = 150, src = getURL("Portlet1")
            }
        ] },
        new Gadget { title = "Portlet2", column = 2, children = [] },
        new Gadget { title = "Portlet3", column = 1, children = [] },
        new Gadget { title = "Portlet4", column = 2, children = [] }
    ]};
    
    function getURL(name String in) returns(String)
        pkg String = "com/ibm/egl/demos";
        baseURL String = document.location;
        baseURL = baseURL[1 : strlib.indexOf(baseURL, pkg)-1];
        return (baseURL + pkg + "/" + name + ".html");        
    end
end


We deployed the second application, in this case Portlet1 in the same location as the main handler, so we use the same base URL to compute the URL for the nested handler. The portlet itself works like a standalone application and can be developed normally using EGL CE. Nothing special is required in its implementation:

handler Portlet1 type RUIhandler {initialUI = [ html ] }
    html HTML {
        padding = 2,
        text = 
"This <b>portlet</b> contains <i>just</i> some HTML. That's it.<p>" +


"Visit <a target=_blank href=http://ibm.com>ibm.com</a>."

    };


The portlets can be dragged around, and here is the result after dragging all the empty ones to the second column:

portal2.JPG
Now let's add a more interesting portlet, such as one where two portlets communicate with each other. We will use the EGL InfoBus, which is based on the standard OpenAjax Hub to send messages between the portal and its portlets.

Our second portlet shows an entry field and a button. Here is the source:

handler Portlet2 type RUIhandler {initialUI = [ html, numberField, goButton ] }
	
	html HTML { 
		margin = 7, font = "Arial", text = "Enter a number:"
	};
	numberField TextField { 
		margin = 7, marginTop = 4, onKeyPress ::= checkEnter, text = "2" 
	};
	goButton DojoButton { 
		text = "Go", margin = 7, onClick ::= go 
	};
	subscription any = InfoBus.subscribe("calculator.result", showResult);
  
	function go(e Event in)
		InfoBus.publish("calculator.calculate", numberField.text);
	end

	function checkEnter(e Event in)
		if (e.ch == 13)
			go(e);
		end
	end
	
	function showResult(msg String in, result any in)
		numberField.text = result;
	end

	fix CrossIFrameInfoBusFix{};
end


Notice it is waiting for calculator requests by subscribing to "calculator.result" messages on the InfoBus. Whenever any handler on the current page does a publish with that message key, Portlet 2 will be notified in its "showResult" function. When the user presses Enter or clicks the Go button, a multiplication request is published on the InfoBus again, to be picked up by Portlet 3 (see below).

Our third portlet implements a calculator that multiplies a number with 2. Here is the source:

handler Portlet3 type RUIhandler {initialUI = [ html ] }
    
    html HTML { font = "Arial", text = "Waiting for Portlet 2..." };
        
    subscription any = InfoBus.subscribe("calculator.calculate", calculate);
    
    function calculate(msg String in, data any in)
    	try 
	    	value bigint = data;
	    	result bigint = 2 * value;
	    	html.text = "2 * " + value + " = " + result;
	    	InfoBus.publish("calculator.result", result as String);
	    onException (e AnyException)
	    	html.text = "Oops: '" + e.message + " " + data + "'";
	    end
    end

    fix CrossIFrameInfoBusFix{};

end


Again, it defines a subscription to the InfoBus, and handles them in its "calculate" function. Once a result is known, we publish it on the InfoBus again. When something unexpected happens, such as arithmetic overflow or the user enters an invalid number, we print a message.

Finally, portlet 4 simply shows another URL, in this case http://ibm.com/

handler Portlet4 type RUIhandler {initialUI = [ frame ] }
	
	frame IFrame { width=1000, height=1000,  src = "http://ibm.com" };
  
end


The end result looks like this:

http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/38-1264-1738/portal3.jpg
Inter-portlet Communication

You may have noticed declarations to the following field in some of the portlets:

    fix CrossIFrameInfoBusFix{};


What this does is include a fix for InfoBus to allow it to work across iframes. Normally a parent and its nested iframes are completely isolated from each other. What the fix allows for is communication between these two different documents.

What if I don't want a Portal?

The above sample shows how to build a client-side Portal using iframes for the individual portlets and InfoBus for communication. You can use the same technique for other compositions of multiple "modules". One example could be having a main handler with a tab folder. As that is all it contains, it will start up quickly. Then as tabs are opened over time, more and more sub-modules are downloaded on demand (using the above IFrame approach).

The nested handlers can be kept around (as in the Portal), but a different policy could be to do some form of "garbage collection" by unloading the iframes from the document, and recreating them from scratch again when the user likes.

By decomposing modules into separate application level URLs, complexity goes down, individual files get smaller, and things will faster initially and will benefit usage patterns where a limited breath of functionality is actually activated by the end user. Some application have hundreds, even thousands of "screens", and putting them all in one single mega-application makes little sense as during any session only a few dozen may be actually activated.

To try this out in your own workspace, import the attached archive as "General > Existing projects into Workspace". Open the Portal.egl application and load it in the preview.

To try out the non-Portal approach, check out "AppSwitcher.egl".

Attachments: Portal.zip

9 Comments Permalink
2

Since 1997 I have been licensing a version of the card game Klondike Solitaire to online gaming sites. I originally wrote the game in 1997 as a learning exercise. It was, for all intents and purposes, my first Java application. Earlier this year I worked for about a month in my spare time to port the Java version of my game to EGL Rich UI. You can play the game here.

While there may be potential commercial clients for my new game, this is less likely today than when online gaming sites were first springing up. Instead of looking for a commercial audience for the EGL version of my game I have placed the source code in the public domain and it is available here on SourceForge.

Perhaps my code can serve as a learning tool for people entering the EGL programming world. Who knows, there might even be people who want to improve upon the game or use it as the basis for other, similar games.

Over the next few weeks I hope to blog more about the experience of porting solitaire from Java to EGL. Here are some of the topics that I think might be of interest to readers:

  • Migrating software from an OO language to a non-OO language. You may be interested to hear just how close EGL is to an OO language and how reasonably it adapts to an OO design model.

  • UI elements that are easier to implement in EGL than in Java. For example, using lowest-common-denominator Java technologies required creating my own drag and drop mechanism. In EGL, drag and drop is a fact of life and it is dead easy to code.

  • Localization on a budget: How I was able to get reasonable translations for next to nothing.

While some might scoff at this effort being a mere game -- and not "serious" software like order entry applications or something (but you know, I write those too) – I would be quick to point out that I've made money from the Java version of this game for more than a decade now. In my book that makes it business software.<grin> If nothing else though, the same user-interface elements that one finds in games today manifest in all modern web applications and most modern back-office applications. You may not care about games as such but as a learning tool I hope my work is still helpful to you.

Dan Darnell, Consultant

2 Comments Permalink
6

In EGL CE, the EGL project structure has been changed to combine and extend the features of the General Project and the Rich UI Project types found in Rational Business Developer (RBD). In RBD, a General Project would be used for Java, and a Rich UI project would be used for JavaScript. In EGL CE, one project can now be used for both languages. Also, when working with Rich UI in RBD, a user had to set the workspace for Development or Deployment mode, depending on whether or not the code was still being written and debugged or if it was being prepared for deployment.

To remove the switch that controls Development mode and Deployment mode, all generated content is now placed into two directories at the root of the project; debug and target. All code that is used for development and debugging will be placed in the debug directory, and all code that will be used for deployment is placed in the target directory. To support the use of multiple languages in one EGL project, the debug and target directories contain a subdirectory for each language being generated; Java and JavaScript.

In addition to the project structure changes found in EGL CE, the way that code is generated has also been changed. In EGL CE, the only parts that are considered 'Generatable' are Handlers and Services, and these parts are now generated whenever the EGL source for the part is built. Any parts that are referenced by a Handler or a Service will be generated whenever the Handler or Service is generated, and they will be generated into the same language as the Handler or the Service. For example, assume a Library is used by both a RUIHandler and a Service. When the RUIHandler is saved, both the Handler and the Library will be generated into JavaScript and placed in the appropriate JavaScript output directories (e.g. debug/JavaScript, target/JavaScript). When the Service is saved, both the Service and the Library will be generated into Java and placed in the appropriate output directories (e.g. debug/Java, target/Java). To support the generation process, each EGL resource in an EGL CE project can now specify 4 different Default Build Descriptors: Debug/JavaScript, Target/JavaScript, Debug/Java, Target/Java.

It was mentioned above that an EGL Part is generated whenever its source is built. In Eclipse, a build usually happens when a file is saved or when a Clean Build is invoked. When a Clean Build is invoked in EGL CE, the root debug and target directories are deleted, and all of the parts in the workspace are regenerated as they are built. Due to the fact that the generation output directories will be 'cleaned' during this process, it is not recommended that you place your own Java code in these directories. If you have your own Java code that you would like to reference using EGL External Types, it is recommended that you add another Java Source folder to your EGL Project and place the Java code in this directory. When you deploy your project, you will also need to copy the Java code into the Java Source folder for that project as well.

6 Comments Permalink
0

EGL CE has recently shipped, and I decided to write a sample that showcases some of the useful features this new and exciting technology offers.

In short, my sample downloads a workitem from jazz.net and shows it in a UI. Of course, my intent is not to replace the Jazz Web UI, rather I highly simplified it into a small sample that shows off aspects found in many rich web applications.

When the JazzUI handler is loaded, it makes a couple of service calls. The following picture shows what components in the UI are created how (it happens to show Darin Swanson, the creator or workitem 33551):

info.jpg

Use of EGL CE Features

My Jazz workitem UI showcases the following EGL CE features:

  • authentication and session management
  • calling asynchronous services (Ajax)
  • decomposition of complexity by composing reusable handlers
  • Dojo Widgets for some of the UI elements
  • browser cookies for storing userid+passwords
  • XML DOM parsing to efficiently deal with large XML files
  • EGL Jobs to manage future work and improve responsiveness
  • an EGL library to implement the singleton pattern (see LoginForm.egl)
  • the EGL InfoBus to decouple producers and consumers of application events
  • the EGL History support to manage the back button and allow for bookmarkability
  • a Service Monitor to trace and debug service calls
  • aggressive compression and optimization when deploying the application

The code is heavily annotated with comments, so I won't show too much sample code in this blog entry and refer simply to the source code that can be found in the attachment.

Deployment and Compression

When I deployed my application in my workspace, I selected the project and used the context menu to deploy it. Then I create a new target project and deployed it on TomCat 5.5.
After it was deployed, I located the generated HTML file in the target project's WebContent folder.

I then used the context menu to run it on TomCat and used Firefox with Firebug to inspect the size of the end-result.

The following picture shows my Dojo files are cached in the browser already (except for jsapi!). Note that the picture shown for the 'creator' is completely random and really comes from bing.com when you search for Bill :-).

firebug.jpg


The 68K for our application HTML file includes the following:

  • all of the EGL runtime,
  • all the EGL widgets I used and that got compiled into JavaScript,
  • all the EGL code I wrote that is compiled into JavaScript,
  • all my hand-written JavaScript that I wrote to implement a few external types,
  • all EGL-specific JavaScript used by the Dojo widgets

As you see in the image above, the dojo widgets themselves come from Google's CDN.

All EGL debugging information has been stripped from the JavaScript, and then we reduced the left-over JavaScript using Dojo ShrinkSafe. This is all done automatically by the EGL CE tooling. Finally, when the application is deployed on TomCat, we tell TomCat to use gzip encoding to further compress the text. All this is automatic without me needing to think about it at all.

Try it for yourself

To try the sample for yourself, follow these instructions:

  • download the attached archive (do not unzip it)
  • in EGL CE, use the menu option File > Import...
  • select Existing Projects into Workspace
  • select the jazz.net.workitem project
  • open EGLSource/ui/JazzUI.egl and select the Preview tab
  • click on the links How's this done? and Source Code

The import dialog should look something like this:

http://www-949.ibm.com/software/rational/cafe/servlet/JiveServlet/downloadImage/38-1261-1732/import.jpg


Attachments

jazzui.zip (make sure to apply the DojoDialog fix: DojoDialog may be incorrectly sized)

0 Comments Permalink
1

One of the cool features of RPG is the "move fields" logic where data is moved from input buffers to program fields and from program fields to output buffers. Most RPG programmers don't think of this as cool - it is so fundamental to RPG that RPG programmers take it for granted.

When the RPG programmer defines a file in the RPG source, the compiler implicitly generates an internal program field for each field in the file, and the compiler also implicity moves data from the I/O buffers to the program fields for read and write operations to the file. If a particular field name appears in more than one file used by the RPG program, the field can be read from one file and then written out to the other file without any effort on the part of the RPG programmer.

Example: Say files FILE1 and FILE2 files have fields NAME and ADDR. A READ operation reads both those fields from file1 and a WRITE operation writes both those fields out to file2. It's not necessary to mention the field names in the source unless the fields are needed for some calculation.

    read FILE1;
    write FILE2;

If a new field CITY is added to both files, and the program is recompiled, the CITY field will automatically be handled by the READ and WRITE. No change is required to the program source.

If you look in your compiler listing, you can see the I and O specs that the compiler generates. These specs are not just descriptions of the I/O buffers. They are executable operations. The I specs are move operations from the Input buffer to the program fields, and the O specs are move operations from the program fields to the output buffer. It is because the I and O specs are executable operations to and from program fields that it's possible to have a field defined as packed in a database file and zoned in a screen file. RPG just does any necessary conversions when it move the data between the I/O buffers and the program fields.

You can see the I and O specs in action by stepping through the I and O specs in the debugger. You have to compile with OPTION(*DEBUGIO) and use the listing debug view.

The "move-fields" logic has always been part of RPG, or I should say it has been at least since RPG II. (I don't know much about the original RPG prior to RPG II.)

The EVAL-CORR opcode (added in v5r4) works in a similar way. If the READ and WRITE operations use data structures instead of using the I and O specs, you can assign all the same-name subfields from one data structure to another without actually mentioning the subfields by name. Just like the example above, the following code will automatically handle the new CITY subfields when the program is recompiled after the CITY fields are added to the files.
    read FILE1 ds1;
    eval-corr ds2 = ds1;
    write FILE2 ds2;


Even though I do think it is very cool the way RPG automatically handles the fields from files, I sometimes wonder if it would be better in the long run for program maintenance to have the movement of field data from file to file be more explicit. But that's a topic for another blog post.

1 Comments Permalink
1

If you are still using the IBM WebFacing Tool as part of WDSC or are running your WebFacing workload on IBM i V5R4 or lower, but are contemplating an upgrade, then do not miss this online event.

This one-hour webinar is targetted towards existing WebFacing users and will provide information about:

  • IBM WebFacing Tool directions and recent enhancements
  • New integrated development environment requirements
  • Changes in IBM WebFacing Tool packaging
  • New deployment requirements and pricing

The webinar will be held on Wednesday, September 2, 2009 at 11:30AM Eastern Daylight Time for one hour.
To register, e-mail your company name, contact name, phone number, mailing address, and e-mail address to Brian King at blking@us.ibm.com or contact him at 1-919-254-4961.

After registering, you will receive additional information on how to join the webinar.

If you have any questions regarding this event, please contact Brian King at the address above, or Al Grega at algrega@us.ibm.com.


UPDATE: To view the recording of this call and to download the charts please visit Replay: Wondering about WebFacing Webinar .

1 Comments Permalink
0

iSeries DevCon Podcast in EGL and i

Posted by JoePluta Sep 15, 2009

I have presented session at iSeries DevCon pretty much since the conference's inception, and this year is no exception. Of course, I'll be doing the heavy lifting on EGL and some other related topics, but there are lots more great speakers and sessions. In my humble opinion, there isn't another conference that better provides both true nuts and bolts programming techniques with a solid application of future-proofing technologies.

Trevor Perry and I have recorded podcasts about what you can expect; click on the link to go to my podcast.

You'll have to enter an email address to get the real link, though.

0 Comments Permalink
0

Hello -- I'm the technical leader for the IBM MASS math libraries. MASS stands for Mathematical Acceleration Subsystem, and consists of libraries of mathematical functions specifically tuned for optimum performance on various computing platforms.

MASS was originally launched by IBM in 1995, and has been continuously improved and expanded since then. I've been involved with MASS since 2002.

There are currently versions of MASS for all the POWER processors, running AIX or Linux operating systems. There are also versions for BlueGene/L and BlueGene/P, as well as the Cell/B.E.

The libraries contain accelerated implementations of elementary functions such as the trigonometric and hyperbolic functions and their inverses; power, logarithm, exponential, error function, and others. Complete lists are available on the MASS Web page, the URL of which is given below.

There are both scalar and vector libraries, and for Cell/B.E. there is a SIMD library as well.

The libraries are callable from C, C++, or Fortran source programs. The IBM XL C/C++ and IBM XL Fortran compilers are also capable of recognizing opportunities to use MASS to accelerate the source program, and invoking it automatically without the need for source-program changes.

The MASS libraries are packaged with the IBM XL C/C++ and IBM XL Fortran compilers, and are also available free-of-charge on the MASS Web page, for users of other compilers (such as gcc) for the target hardware.

You can find out more about the MASS libraries at the MASS Web page, http://www.ibm.com/software/awdtools/mass . If you have questions about MASS, you can post them on this blog, or send them to me at masslib@ca.ibm.com, both of which I monitor.

Happy numerical computing!

Regards,
Robert


Robert F. Enenkel, Ph.D.,
Compilers/Numerical Computing, IBM Toronto Laboratory,
Mail Stop D2, 8200 Warden Ave., Markham, Ontario, Canada, L6G 1C7
https://www-927.ibm.com/ibm/cas/toronto/people/members/robert.shtml

0 Comments Permalink
1 2 3 4 ... 16 Previous Next
Bottom Banner