SharenGo Wiki
About Sharengo
- SharenGo
- Members
- Join us
- Contact

Methodology
- Methodology

Tools
- PragMaTic
- ABS
- JsRIA

Projects
- MarcoPolo

Components Directory

Infrastructure
- HAPlatForm

Legal

Community
- Tracker
- MailingLists

Wiki
- WikiHelp
- RecentChanges
- RSS
- WikiSearch

HelloWorld

Prerequisites

  • Last version of the toolchain is installed. For our example, we install the toolschain in a directory "abs" called $ABS_HOME
  • $ABS_HOME/tc/ant/bin must be in PATH
  • The Poseidon UML model of the exemple can be found here : hello-conception.zuml but try to create everything by yourself
NOTE : all commands are executed on a linux workstation, it works on windows too but you need to do some small translations.

1 Creating the project


First, we want to create a dedicated workspace named test for all our experimentation.
cd $ABS_HOME
abs new.workspace
/home/$USER/test
Then we go to our workspace directory and create a new project.

cd /home/$USER/test
abs new.project
tutorial1
A project is an aggregation of modules and components. The difference between a module and a component, is that a component may be reused outside the context of a given project. A module is definitively linked to one project.

In order to have some code, we have to create a module in our project.
cd projects/tutorial1

2 Adding a module


We want to create a module named hello
abs dep:add.mod
hello
The script create a new module directory in /home/$USER/test/projects/tutorial1/modules.

3 Creating the conception model


The objective is to create an application with an html interface asking for a name and printing a string "Hello" and the name (very original, isn't it ?)
Each module and component, can have three differents parts depending on the internal architecture of the application :

- a client part if you want to manage a SWING interface or others
- a common part if you want to create a standalone library of group some classes used in server and client parts
- a server part running in a server container

Here we have only a server application to build.

So we build an UML model of our application with Poseidon and store the model in /home/$USER/test/projects/tutorial1/modules/hello/server/model/conception.
We apply a standard architecture with servlet, ui, view and process classes.
In order to be correctly generated each class have to specify her own stereotype.
Here we use four differents stereotypes :
- servlet
- ui
- process
- view

The servlet is used as a controler to route user request to the correct ui object.
The ui manage all the user interface related work
The process contain all business related processing
Each view object is related to a specific html page.

We have to specificy a relation between servlet and ui class. The end of the relation on the ui side must be named "ui". This is necessary to automatically generate use of the factory mecanism. The same apply between ui and process. The relation on the process class side must be named "process".

We have :
a HelloServlet class
a HelloUI class
a HelloProcess class
a HelloFormView class
a HelloAnswerView class

We create all those classes in a package org.sharengo.tutorial1.



We save the model. It must be named conception.zuml. All conception models must be named conception.zuml.

4 Specifying the dependencies


Our module is build on the standard SWAA sharengo architecture. So we use some libraries to be independant from all the persistent mecanism and template engine specificities.
We have to express the differents components and library we need to use.
There is two kind of dependancies : source dependency wich are related to source component store in various scm repositories and binary libraries dependencies related to code not stored in scm.
First we add a source dependency on the gluon component. This component is located in the sharengo subversion repository. Note that your repositories.properties must be configured to authorize access to this repository.
Here is an example of repositories.properties, you must have in your $ABS_HOME directory.

# list of repositories
repositories = sharengo
#default repository
default=sharengo
# definition of sharengo source repository
repository.sharengo.type=svn
repository.sharengo.url=http://svn.sharengo.org
repository.sharengo.username=anonymous
repository.sharengo.password=anon
So now we want to add a dependency on component "gluon" at version 3. All the gluon family of components are middleware used to wrap all access to technical component layer (configuration, template engine, persistence layer, etc).


cd /home/$USER/test/projects/tutorial1/modules/hello
abs dep:add.src
middleware/gluon/tags/3.1
If the component is not locally installed, the script will failed with the message "component [middleware/gluon/tags/3] not found". We have first to create the gluon component in the chain.

cd /home/$USER/test
abs new.scm.component
middleware/gluon/tags/3.1
sharengo
The script checked if a component with that name exist in the sharengo subversion repository and install it locally
cd /home/$USER/test/projects/tutorial1/modules/hello
abs dep:add.src
middleware/gluon/tags/3.1
This time the dependency is accepted.

Start again with gluon-velocity. This component offer an implementation of standard template engine based on velocity template engine.
cd /home/$USER/test
abs new.scm.component
middleware/gluon-velocity/tags/3
sharengo
cd /home/$USER/test/projects/tutorial1/modules/hello
abs dep:add.src
middleware/gluon-velocity/tags/3

All the applications use the common-logging package from jakarta to process log informations.
This is a binary package.
abs dep:add.bin
commons-logging.jar
as well as the common-collections package:
abs dep:add.bin
commons-collections-3.1.jar
Next our servlet class will extends the HttpServlet class. So we have to use the servlet4.jar. But we don't want this package to be included at deployment time. To do this, we have to prefix the name of the package with a '-' character.
abs dep:add.bin
-servlet-4.jar
At last we decide to use log4j component to process all logs informations from the application (this application doesn't know about log4j API, but we have to declare an implementation in order to have something).
abs dep:add.bin
log4j-1.2.8.jar

5 generating code


abs mda:gen.java.local
nine classes are generated (yes, i know it's a lot just to be able to print "Hello", but when you want to build large applications with reusable components, that's the price to pay).
./server/main/src/fr/openmodel/tutorial1/I_HelloProcess.javainterface for the process
./server/main/conf/HelloServlet-servlet.web.xmlservlet declaration section used in web-apps descriptor : web.xml
./server/main/src/fr/openmodel/tutorial1/Impl_HelloProcess.javaimplementation of the process
./server/main/src/fr/openmodel/tutorial1/GenericHelloProcessException.java generic exception for all process error
./server/main/src/fr/openmodel/tutorial1/FormView.javaview for form page
./server/main/src/fr/openmodel/tutorial1/AnswerView.javaview for answer page
./server/main/src/fr/openmodel/tutorial1/HelloServlet.javaservlet
./server/main/src/fr/openmodel/tutorial1/I_HelloUI.javainterface for ui
./server/main/src/fr/openmodel/tutorial1/Impl_HelloUI.javaimplementation for ui
./server/main/src/fr/openmodel/tutorial1/GenericHelloUIException.javageneric exception for all ui error

6 Compiling


We can try a first compilation, just to see.
cd /home/$USER/test/projects/tutorial1/
abs lib:all
first the script download the binary components not available locally (servlet4.jar, commons-logging, log4j-1.2.8).
then everything is compiled.
BUILD SUCCESSFUL, great.

7 integrating project in IDE


In order to work in a known environment, we can generate project files for NetBeans? or Eclipse.

For NetBeans fans :

cd /home/$USER/test/projects/tutorial1
abs netbeans:gen.all.project
For Eclipse addicts :

abs eclipse:gen.classpath.full.src
abs eclipse:gen.project
Then, you must set two classpath variables (Window -> Preferences ; Java -> Build Path -> Classpath Variables) :
  • ABS_BINARY_REPOSITORY : /path_to_abs_home/binary-repository
  • REPOSITORY_PATH : /path_to_workspace_dir/

You can now open the project in your favorite environment.

8 Adding methods


Now in order to have something useful (?) we have to add new methods
We create a sequence diagram showing the differents methods to use in order to show the first form.
A first method showForm must be created in the ui class. UI method get in general at least one parameter corresponding to the OutputStreamWriter object used to send something to the user.
We have to import the class in our model or create a dummy class with the same name in order to be able to specify the type of the parameter of our showForm method. the OutputStreamWriterClass? must have the "extern" stereotype in order to not generate class.
The import directive will be automatically added.
NB: every time you use a new class in your hand writed code, you must declare it in your model.


All the methods of UI classes which can generate exception must generate generic exception related to the class owning the method. This is done to have stable signature for all methods. The generic exceptions can encapsulate more specific one.
All constructors of view object need two parameters :
- a reference of the current template engine to use. UI objects are automatically equiped with such a reference.
- a reference of the current OutputStreamWriter to use

Adding method on FormView class
We just add a show method with no parameter and no return value. PragMatic? will add proposed code to render the template manage by the view.


9 Generating code


cd /home/$USER/test/projects/tutorial1/modules/hello
abs mda:gen.java.local
cd /home/$USER/test/projects/tutorial1
abs lib:all
or use the generate target from your IDE.


10 Adding manual code


in HelloServlet doExec method

The default action must be to show an empty form.


private void doExec(HttpServletRequest request, HttpServletResponse response)
throws ServletException
{
ServletApplContext context = new ServletApplContext(request, response);
String action = context.getParamValue(ACTION_LABEL);
/************************ BEGIN HGC (handle with care) ***********/
/**************************** END HGC *************************/
try
   {
   OutputStreamWriter osw = new OutputStreamWriter(response.getOutputStream());
   if (action != null)
     {
/************************ BEGIN HGC (handle with care) ***********/

/**************************** END HGC *************************/
     }
   else
      {
/************************ BEGIN HGC (handle with care) ***********/
      ui.showForm(osw);
/**************************** END HGC *************************/
      }
   }
catch (Exception e)
   {
   log.error("Error ["+e+"]processing request with action ["+action+"]");
   throw new ServletException(e);
   }
}


In Impl_HelloUI showform

public void showForm(OutputStreamWriter oswthrows GenericHelloUIException
{
/************************ BEGIN HGC (handle with care) ***********/
HelloFormView fv = new HelloFormView(tplEngine, osw);
fv.show();
/**************************** END HGC *************************/
}





11 Creating template file

<html>
<body>
	 <form method="POST" action="helloservlet">
         <input type="hidden" name="action" value="sayhello">
	 Name : <input name="name" type="text" size="30" maxlength="30">
	 <input type="submit" value="ok">
	 </form>
</body>
</html>
save the file as "HelloFormView.vsl" in hello/server/main/conf directory.

12 Adding configuration in conception model


Everything must be define in the conception model. We have to describe all elements related to configuration.
For that, we use a specific stereotype "jndiconf" and create a class "helloconf". All the attributes contained in a class with this stereotype will become a parameter in the jndi context.
Some tag values will add information about the exact nature of each parameter (factory configuration, simple application parameter, ...).
Here, we need two factories, one to create the ui class and the other to create the process class.

The principle used to declare factory is :
- declare a parameter whose name is the interface we want to retrieve
- the default value will be the implementation we want to use (value:org.sharengo......)
- a special tag value identify the parameter as a factory configuration value (factory:true)
- another tag value define this configuration parameter as global (global:true). A local parameter is prefixed in the jndi tree by the name of the current class. For example for a parameter "foo" the global name will be "foo" and the local name will be "helloconf/foo".

We define two attributes : I_HelloUI referencing org.sharengo.tutorial1.Impl_HelloUI implementation and I_HelloProcess for org.sharengo.tutorial1.Impl_HelloProcess.



We write a velocity configuration file (velocity.properties) and store it in directory "hello/server/main/conf".

velocity.properties:
resource.loader = class
class.resource.loader.description = Velocity File Resource Loader
class.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
class.resource.loader.cache = false
class.resource.loader.modificationCheckInterval = 0

13 Code generation again

cd /home/$USER/test/projects/tutorial1/modules/hello
abs mda:gen.java.local

14 Configuring log component


we add a file log4j.properties in directory "hello/server/main/conf" to specify what kind of processing we need for standard application log.
For example
log4j.properties:
log4j.rootCategory=DEBUG,A1
log4j.appender.A1=org.apache.log4j.FileAppender
log4j.appender.A1.File=/home/$USER/catalina.out
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n



15 Creating a new deployment target


cd /home/$USER/test/projects/tutorial1
abs deploy:new
localhost

16 Generating the deployment package


abs lib:all
abs deploy:build.war
a war file is now available in /home/$USER/test/projects/tutorial1/deployment/localhost/server


17 Deploying the package


You can deploy with your favorite tools or if using Eclipse or Netbeans embedded tomcat using the related target.
Add these lines in the catalina.sh file :
export JAVA_OPTS=-Dconfiguration.builder=fr.openmodel.configuration.JNDIConfigurationBuilder
export JAVA_OPTS=$JAVA_OPTS" "-Dtemplate.engine.builder=fr.openmodel.template.VelocityTemplateEngineBuilder
and restart tomcat.

18 Testing


http://localhost:8080/tutorial1/helloservlet
Our simple form appeared.



Now we want to add a method to prepare the answer page.

19 Adding new method


We add two methods in AnswerView
- setMessage to inject the name field from the form in the answer page

public void setMessage(String name)
- show (same as FormView)
and a mapping for the message name (msg in the template) through the static attribute MSG.

One method in HelloProcess, "buildMessage" to prepare final message.
public String buildMessage(String name)
One new method in HelloUI, "sayHello".
public void sayHello(OutputStreamWriter osw, String name)

20 Generating code


cd /home/$USER/test/projects/tutorial1/modules/hello
abs mda:gen.java.local

creating a new template (file HelloAnswerView?.vsl in hello/server/main/conf directory)
<html>
<body>
The message is : $msg
<p>
<a href="helloservlet">One more time</a>
</body>
</html>

21 Adding manual code


in Impl_HelloUI

   public void sayHello(OutputStreamWriter osw, String name)
      throws GenericHelloUIException {
      try {
        /************************ BEGIN HGC (handle with care) ***********/
        HelloAnswerView av = new HelloAnswerView(tplEngine, osw);
        String msg = process.buildMessage(name);
        av.setMessage(msg);
        av.show();

        /**************************** END HGC *************************/
      catch (Exception e) {
        log.error("Error during sayHello execution", e);

        String[] args = getClass().getName()"sayHello" };
        throw new GenericHelloUIException(GenericHelloUIException.EXECUTION_METHOD_ERROR,
           args, e);
      }
   }


In Impl_HelloProcess

   public String buildMessage(String namethrows GenericHelloProcessException {
      try {
        /************************ BEGIN HGC (handle with care) ***********/
        return "Hello " + name;

        /**************************** END HGC *************************/
      catch (Exception e) {
        log.error("Error during buildMessage execution", e);

        String[] args = getClass().getName()"buildMessage" };
        throw new GenericHelloProcessException(GenericHelloProcessException.EXECUTION_METHOD_ERROR,
           args, e);
      }
   }


In HelloAnswerView

   public void setMessage(String name) {
      /************************ BEGIN HGC (handle with care) ***********/
      tpl.setValue(MSG, name);

      /**************************** END HGC *************************/
   }


And we modify the code in the HelloServlet :


      try {
        OutputStreamWriter osw = new OutputStreamWriter(response.getOutputStream());

        if (action != null) {
           /************************ BEGIN HGC (handle with care) ***********/
           if (action.equals("sayhello")) {
              ui.sayHello(osw, context.getParamValue("name"));
           }

           /**************************** END HGC *************************/
        else {
           /************************ BEGIN HGC (handle with care) ***********/
           ui.showForm(osw);

           /**************************** END HGC *************************/
        }
      catch (Exception e) {
        log.error("Error [" + e + "]processing request with action [" +
           action + "]", e);
        throw new ServletException(e);
      finally {
        if (log.isDebugEnabled()) {
           log.debug("Request proceed with action [" + action + "]");
        }
      }



22 Compilation, deployment, test

cd $ABS_HOME/projects/tutorial1
abs lib:all
abs deploy:build.war

23 Deploying, testing


DONE

24 Adding project in scm repository


abs scm:initial.import



HelloWorld is mentioned on: abs tutorials


VeryQuickWiki Version 2.7.1 | Admin
Contact -