Blog Posts

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

Standards love to add things. They remove very little, but they do like to deprecate. This post will describe a collection of things that is heading that way, or not heading that way in C++ 0x.

In my posting on Intention to deprecate trigraphs in the next C++ Standard, we successfully demonstrated that much of the non-English speaking world will still need to rely on trigraphs as a way to get to UCN through "\" which may be inaccessible in some codepages. So we would object to deprecating it without an alternative.

In the last meeting in Santa Cruz, an alternative was proposed in Core issue 789:Replacing Trigraphs. In short, it does not so much deprecate trigraphs (which we like) as move trigraphs out of translation phase 1 so trigraphs are not recognized ahead of raw strings, but is still recognized ahead of other strings (as it is now). It seems that trigraph interaction with raw strings was always the real issue behind the original National Body comment. This interaction had become more prevalent because Raw strings are accepted as part of C++0x. This proposal will level the playing field to what it was again.

We reviewed the paper as a way of fixing the interaction of trigraphs and raw strings. We think the paper is ready to go, but we're holding it back because we're considering other approaches, including moving UCNs out of translation phase 1 or moving raw string recognition into phase 1.

We're still looking at deprecating exception specifications. Our current feeling is that we will deprecate them except for the ways of saying a function doesn't throw at all (e.g., the new noexcept feature, still being reviewed). This feature has been shown to be relatively useless since its inception.

We did a straw poll on deprecating or removing exported templates. I voted to support removal of export to reduce dialecting C++. However a straw poll in full committee seems to prefer deprecation. This feature has been implemented exactly by one company, and even their lead is not opposing its removal. We appreciate their selfless sense of the C++ community and appreciate their sacrifice in learning about why this feature was problematic. Sometimes, it does take doing to see the whole picture.

Finally, we deprecated the semantics of the register keyword. This keyword has been ignored by most compiler that I am aware of, so it is the right time to deprecate it.

As with all deprecation, have no fear. All compilers will generally continue to accept (and or ignore) these cases, so that your code will continue to compile.

0 Comments Permalink
0

The Library side brought about some of the most interesting changes. I already discussed the key discussions with respect to unifying the Asynchronous futures proposal in The View (or trip report) from the Oct 2009 C++ Standard meeting.

This resulted in a paper which will be published in the upcoming mailing (in about a week from now), which will show the approach on Asynchronous Call A Simple Asynchronous Call.

The key changes there were:

  • A restoration of the variadic thread and async functions. This restoration is a consequence of analysis and request of the British Standards Institute.
  • A convergence on the "as if a new thread" in the launching of asynchronous work. This change avoids undefined behavior arising from any delay in destroying thread-local variables, but requires careful implementation to avoid excessive overhead.
  • Removal of the is_ready, has_exception, and has_value query functions. The presence of these function requires still other functions in the synchronous case. Evolution Working Group direction is that the complexity in interface is as yet unjustified, and prudence dictates a smaller initial interface.
  • Unspecified behavior for the use of timed wait functions when the unique_future was created from a deferred async.
  • The conversion from unique_future to shared_future will execute any deferred work.
  • The use of an enum class to better clarify the launching policy.

The other papers which support this is a resolution of most of the futures issues from National Body comments in Issues on Futures (Rev. 1) . A future describes components that a C++ program can use to retrieve in one thread the result (value or exception) from a function that has run in another thread.

These components are not restricted to multi-threaded programs but can be useful in single-threaded programs as well.

The other resolved issues include:



  • moves swap from the <algorithm> header to <utility> to address UK 300 because swap has become a common utility operation with several common idioms relying on it




Most of these are motivated by National Body comments from CD1. This shows the effort and focus of the committee during these periods as we continue to resolve the almost 600 comments that was received from the September 2008 CD1 draft.

There is now plan to issue a second draft for comment (post removal of Concepts, and with the fixes like above from CD1 comments). This will be CD2 and will be aimed for release after the next meeting in March 2010, in Pittsburgh hosted by Carnegie Mellon.

I will describe in another post more details on the schedule changes which is now clearer and I have updated in the C/C++ Standard hub

0 Comments Permalink
0

Santa Cruz is a wonderful location for us to decide weighty matters such as how best to ship a C++ Standard with the overloaded number of issues. Normally a surfing town as I am told, I have not had a chance to even make it to the ocean shoreline as yet even though I am only mere blocks from it. So busy we are that let me waste no more time and recap.

1. P.J. Plauger (or Bill Plauger) has been the convener of the C++ meeting. There was an attempt to stop processing any new features in order to facilitate our promised shipping date for the Standard. The problem is what is new? Some issues are discovered late and are serious if not fixed. Some new issues are truly wish list and should be stopped. Other issues are somewhat in between but need to be weighted with all the other.

The vote that tried to stop all new feature failed probably because of how ambiguous the wording is, in my opinion. The issue isn't about stopping consideration of any new feature, but balancing all features based on their seriousness and only being able to handle a fixed number of them based on resource.

But the problem with that model of triage (which is often done in software industry), is that we are all volunteers and you just can't easily make volunteers do the hard thing, when they would rather do what they like.

The end result is that P.J. Plauger has tendered his resignation as convener. I and many would like to thank him for his service and his guidance which has enabled C++ meeting hostings well into 2011.

2. Both Evolution and Core Committees met in addition to Library. Evolution had to deal with a number of pending additions which had been long promised. The most significant discussion is the proposal to add Asynchronous and Futures to C++. This is a higher abstraction for concurrency that allows independent action with a return value.

This was controversial because there were two leading candidate proposals. The majority of the discussion allowed a unified proposal which offered:

  • A restoration of the variadic thread and async functions. This restoration is a consequence of analysis and request of the British Standards Institute.
  • A convergence on the "as if a new thread" in the launching of asynchronous work. This change avoids undefined behavior arising from any delay in destroying thread-local variables, but requires careful implementation to avoid excessive overhead.
  • Removal of the is_ready, has_exception, and has_value query functions. The presence of these function requires still other functions in the synchronous case. Evolution Working Group direction is that the complexity in interface is as yet unjustified, and prudence dictates a smaller initial interface.
  • Unspecified behavior for the use of timed wait functions when the unique_future was created from a deferred async.
  • The conversion from unique_future to shared_future will execute any deferred work.
  • The use of an enum class to better clarify the launching policy.

Interestingly, this discussion really only have bearing on two Library proposals which I will detail in a following blog post.


The formal motions for C++ Core language which resulted from this include the usual group of defect fixes, numbering into the 70 range. Basically, all Ready and Tentatively Ready issues of
n2962 except issues 799, 812, 861, 919, and 920.

There was also a paper called Reaching Scope of Lambda Expressions

n2998
Current lambdas restrict the referents of a lambda expression to the immediately-enclosing function or lambda expression. This restriction is severe and does damage to the utility of the lambda feature.

For example, a simple matrix multiplication kernal would require two enclosing scopes and there would be no captures. It is essentially equivalent to saying that the body of a nested loop cannot access function parameters.

Much of this is from the paper.

Consider the following function to multiply square matricies.


matrix operator*( const matrix& a, const matrix& b )
{
    int n = a.numrows();
    matrix c( n, n );
    for ( int i = 0; i < n; i++ ) {
        for ( int j = 0; j < n; j++ ) {
            double t = 0.0;
            for ( int k = 0; k < n; k++ ) {
                t += a[i][k] * b[k][j];
            }
            c[i][j] = t;
        }
    }
    return c;
}

Its rewrite into functions and lambdas, as intended by the adopted N2550, is as follows. Note that the rewrite is approximately the same size.


matrix operator*( const matrix& a, const matrix& b )
{
    int n = a.numrows();
    matrix c( n, n );
    for_range( 0, n-1, [&]( int i ){
        for_range( 0, n-1, [&]( int j ){
            double t = 0.0;
            for_range( 0, n-1, [&]( int k ){
                t += a[i][k] * b[k][j];
            } );
            c[i][j] = t;
        } );
    } );
    return c;
}

However this straightforward reformulation is ill-formed as per N2927 wording for 5.1.1 expr.prim.lambda paragraphs 9–12. To make the code well-formed, the function must be rewritten as follows, where inserted text shows new code, which sometimes alter variable references.

matrix operator*( const matrix& a, const matrix& b )
{
    int n = a.numrows( );
    matrix c( n, n );
    for_range( 0, n-1, [&]( int i ){
        const matrix& a1 = a;
        const matrix& b1 = b;
	int& n1 = n;
	matrix& c1 = c;
        for_range( 0, n1-1, [&]( int j ){
            const matrix& a2 = a1;
            const matrix& b2 = b1;
	    int& n2 = n1;
	    int& i2 = i;
            double t = 0.0;
            for_range( 0, n1-1, [&]( int k ){
                t += a2[i2][k] * b2[k][j];
            } );
            c1[i][j] = t;
        } );
    } );
    return c;
}

Such extensive mechanical editing will inhibit use, make errors more likely, and complicate code maintenance. Such editing is properly the domain of the compiler.

A third proposal n2989 "Unified Function Syntax" was not moved after significant discussion on whether it solved significant problem or not especially at this late stage, or just merely being a stylistic wish, especially if you have written large amounts of lambdas with the late specified return syntax and found current syntax ugly.

There was controversy because a previous proposal on auto lambda syntax was moved on the contingency that there would be room to explore a unified function syntax. However, as with all agreement in such a committee, the promise is always to allow the work to go forward with all the resource costs (such as authors and collaborators working together, review committee going over the proposal in this case over eight hours over several day), but there is no promise that it would be accepted. Such was the case, and of course the disappointment of the authors of this paper.

Well, in the next posting I will go over the Library proposal.

0 Comments Permalink
0

This is the meeting that closes on all new features for the upcoming C1X Standard (with only a few minor known exceptions)

In this meeting, we processed a number of key issues. We incorporated a few additional details to the memory model and concurrency proposals taken from C++ Standardization. We moved zero-initialization for thread locals from 5.1.2p1 to integrate with 6.7.8p10

One proposal removed gets() from the standard. This has been a problematic function, and was made obsolete in TC3. The function gets() has been problematic because of uncertain newline removal. The answer for a long time is to use fgets() instead.

We reviewed whether C wishes to support a general syntax for attributes similar to C++. This was rejected as most members were uncomfortable with the need and the consequences. Instead, C will adapt keywords prefixed with a single underscore for future attributes. For example, the alignment proposal will use _Align.

Personally, I feel this will cause C more problems in the future as attributes proliferates. But I do not think it precludes future adaption of a generalized system, if the need becomes serious. although right now the consensus is that C does not want general system for attributes.

I also pitched the concept of a common vectorized type for C based on OpenCL. There was general enthusiasm for the feature as many felt the need to drive for future parallelization support based on many existing implementations of vector extensions. However, due to C1X being on a schedule for completion of features, and the relative size of this proposal, the members felt that this proposal need time to develop. Furthermore, there was interest in maintaining close liaison with OpenCL to ensure we do not create dialects of OpenCL if we were to pick subsets.

In the end, the meeting closed with great belief that we are on track to have a feature completed draft by the next meeting in April, 2010. This puts C on a very promising track to finish on time.

0 Comments Permalink
0

Hi all, my name is Michael Wong. I will be attending the next C Standard meeting in Santa Cruz on Oct 26-30, representing IBM and Canada.

This promises to be a critical meeting as it is where the C Committee has nominated as the cutoff for adding features to the upcoming C1X (the code name for the next release of C).

One of the paper is the IBM comment on the Bounds Checking Library:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1388.pdf

where we have made responses as follows:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1389.pdf

IBM has also submitted one more proposal in addition to others.

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1408.pdf

This is a proposal to suggest work to start on a common vectorized type that will be native in C. Currently, the situation is like a jungle out there in that there is a proliferation of vector types from various platforms. Even within one compiler, there are many different vectorized type support because a compiler may need to support VMX, VSX, (Altivec), SSE2, MMX, OpenCL, to name a few.

This has caused a profusion of vectorized names which are similar but possibly not extendable as wider vector registers appear. It is also a recipe for non-portability of code.

The other part of the proposal uses OpenCL as a way to suggest one possible model (but not the only one) of how to support a common Vectorized type.

Please have a look and give me feedback if you wish.

And if you are in the Santa Cruz area, please join us, but first let me know so we can add you to the guest list as the meeting room space is limited based on the projected attendees.

Thanks and I will give a trip report post-meeting.

0 Comments Permalink
0

I am attending the C++ Standard meeting in Santa Cruz. We have a number of issues of interest to us.

SCARY iterators is a way to improve portability invented by our IBM Watson Lab and collaborated on with testing using the xlC++ compiler. It also can give significant performance gains, especially in Blue Gene software:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2913.pdf

The other issue of interest is continuing discussion on resolution to the Trigraph deprecation issue. Although the idea of deprecation was rejected in Frankfurt, there was a desire to reach a common solution by replacing trigraph with something else. A paper was produced and we will review it in the next meeting:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2978.pdf

The solution will resolve many of the issues in my previous posts about trigraphs but we do have some comments. On the whole, we are pleased with this compromise approach.

The other issues that will be discussed will be how to control the proliferation of issues that could cause a prolonged delay of publication of the Standard.

Like any software delivery, shipping a Standard meets the same problems in that there will be many late issues come up out of integration and testing. Some of those will be new, while others are critical fixes. All issues need to be considered fairly through a triage process to see whether they are critical enough to require fixing before shipping, or can afford to be delayed until post-shipping.

This process as obvious as it is to do is not something that is easy to do at the Standard level where work is voluntary. There will be repercussion to this as we move forward if we do not adequately resolve this.

0 Comments Permalink
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
1 2 3 ... 16 Previous Next
Bottom Banner