DIF Tutorial - Building the application

Back to Application Structure

Finally we get to the meat of the tutorial: the coding! On this step we will learn how to translate our app structured under the DEM into Java.

As you might recall, DIF uses a complimentary declarative programming model to inject special behavior on the entities and to define the metamodel structure as well. Don't panic! You will not leave the Java realm, and even better, you will not spend many hours delving in XML files. You might be getting suspicious that this declarative programming model might have something to do with Java Annotations. And you're right! DIF offers a set of Java annotations that allow you to configure your application from the source files. There's no big deal with these annotations. Most of them you will use sparsely, so you don't need to memorize them all. Others you will use more frequently and so after a couple of hours you should know them back to front. If you need to inject more advanced behaviors on your app you might want to check the annotation section of the Reference.

Ok, I'm talking too much, specially when I told you we were going to code. So let's get to it!

Provider

On the previous page I told you that a DIF app must be organized in a certain way, so we will have to do it here. The first thing to do is to define a Provider for your app. This is done by creating a new Java class and annotating it the proper way. The class should be placed on the "pt.digitalis.entities.providers" package, that is on the "survey/src/main/java/pt/digitalis/entities/providers" folder. We will name the Provider with "DemoProvider" on this tutorial but this might typically your organization or project name. Here's the code:

@ProviderDefinition(name="Demo Provider")
public class DemoProvider {
}

To define a Provider you use the annotation @ProviderDefinition. It has a mandatory attribute named "name" (odd thing to write!) that describes the Provider. There are other attributes you can use on the @ProviderDefinition annotation but we are skipping them now.

Application

Next, if you recall what I said, you have to create an Application. This is another annotated Java class. I also said before that the app would be named "Surveys" (remember the archetype?). It should be placed on the package "pt.digitalis.entities.applications", that is on the "survey/src/main/java/pt/digitalis/entities/applications" folder. Here's the code:

@ApplicationDefinition(name="Surveys Application", provider="demoprovider")
public class Surveys {
}

To define an Application you use the annotation @ApplicationDefinition. It has two mandatory attributes: a "name" that describes the Application and a "provider" that associates the Application with a Provider. If you are shrewd enough you might have noticed that I associated the Application with a Provider named "demoprovider", but I haven't written the word "demoprovider" before on this page. I wrote "DemoProvider" several times, but not "demoprovider" (yes, my friend, case matters...after all this is Java!). So what's happening here? Simple! DIF is working for you. The framework is doing what until now you thought that was your job to do: bind things together! Not anymore! At least, not with DIF. You might be curious to find out what's happening under the hood, so I'll shed some light upon that. When you name an entity the framework generates an id for that entity that will be used to bind it to other entities. All entities have ids, even if you can't seem them. But how did I knew that my Provider's id was "demoprovider" and not "RASPIOLA VERUNDUM BISGANIA NIFER" for the matter? Well, there's actually a rule for id generation: it's the lower-case version of the annotated class name. Now you might be thinking "what if I want to supply my own id"? No problem! You would simply add another annotation attribute named "id" and roll out your value. Just remember that your id will be set to lower-case.

Service

Getting further down on the entity hierarchy we had the Service. Once again this will be an annotated Java class. As for the name, I suggest "PersonalInfo", since this will be a personal information survey. This class should be placed on the package "pt.digitalis.entities.services", that is on the "survey/src/main/java/pt/digitalis/entities/services" folder. Here's the code:

@ServiceDefinition(name="Personal Information", application="surveys")
public class PersonalInfo {
}

To define a Service you use the annotation @ServiceDefinition. It has to mandatory attributes: a "name" that describes the Service and an "application" that associates the Service with an Application. By now it should be ok with you the value of the "application" attribute. It's the same binding mechanism based on the id that I described before.

At this point, you might be surprised with two things: how easy is to set the entities hierarchy and that until now we didn't write a single line of runnable code. While the things will stay simple and easy, the coding part will change (thank God, you might be thinking...).

Stage

So it's time to set the next hierarchy level: the Stage. It will contain our business execution logic so we got code to write here. You shouldn't be surprised if I tell you that it will be another annotated Java class. And you should be anticipating that it will belong to package "pt.digitalis.entities.stages" that is on the "survey/src/main/java/pt/digitalis/entities/stages" folder. For the class name we will choose "PersonalData" since it will contain the business logic of our personal information survey. Let's get to the code:

@StageDefinition(name = "Personal Data Input Stage", service = "personalinfo")
@View(target = "PersonalData.jsp")
public class PersonalData {
   
    @View(target = "Success.jsp")
    ViewObject successView;
    
    @Context
    IDIFContext context;

    @Parameter(constraints = "required", linkToForm = "personal")
    String name;

    @Parameter(constraints = "required", linkToForm = "personal")
    Long age;

    @Parameter(constraints = "required", linkToForm = "personal")
    String sex;

    @Parameter(linkToForm = "personal")
    Boolean married;

    @InjectParameterErrors
    ParameterErrors errors;

        public List<Option<String>> getSexOptions() {
        List<Option<String>> options = new ArrayList<Option<String>>();

        options.add(new Option<String>("M", "Male"));
        options.add(new Option<String>("F", "Female"));

        return options;
    }

    @OnSubmit("personal")
    public ViewObject onSubmit() {
        if (!errors.hasErrors()) {
            SurveyBean survey = new SurveyBean();
            survey.setName(name);
            survey.setAge(age);
            survey.setMarried(married);
            survey.setSex(sex);

            this.context.addStageResult("survey", survey);
            
            return successView;
        }
        else
            return null;
    }
}

Ok! Lot's of stuff to chew here. First thing you might notice is that I'm using @StageDefinition annotation to define the Stage. As usual, it has two mandatory parameters: "name" and "service". You've seen this several times before, so I'm not going to spend more time on this.

Then I used another annotation on the class, that is @View. This is used to define a view associated to the Stage. As you can see, you can annotate either the class or the attribute with it. When used on the class it defines the default view associated to the Stage. The default view is the first view that the user sees. That is the entry point to the Stage. You can define other views, as I did above, and later on redirect the user to one of those views based on the application state. You can see that @View has a mandatory attribute: "target". This attribute defines the name of the view that will be executed. As you can see, here we are using JavaServer Pages (JSP) as the view rendering technology. DIF supports other technologies but for now we'll stick to JSP. Also, the framework infers the view type from the view name to choose the appropriate render.

So, now you know how to define an entry and an exit point for your Stage.

The next annotation used is @Context. To understand what it does I have to tell you before about the execution context. The execution context is a record of the application state. It's there that you can store results, information for other stages to process, request redirections, and several other things. Later on I will need to store some results there so I need it to be available. To do so, I create an attribute of the IDIFContext type and annotate it with @Context. Later on, when the framework processes my request, it will remember that I need the context accessible on my stage and will make it available.

There are four attributes annotated with @Parameter. This annotation injects parameters on the annotated attribute. You can think of parameters as bridges between the user's data and the Stage. In this example the user will input data on an HTML form whose field values will be injected on the annotated attributes. Take a careful look at this annotation. It has two attributes and they're both optional: "constraints" and "linkToForm". I'll start by the second one. This might be pretty obvious but I have to tell you the same way. This attribute tells the framework to look for a form with a given name on the default view, find a field with the attribute's name and inject the field's value on the attribute. It looks pretty much, but it's really simple, and once you'll learn to use this feature you will never want anything else. The first attribute, "constraints", has a "required" value which means that the form field must be filled. Take notice that the married attribute does not present the REQUIRED constraint. Later on we will get back to this. There would be a lot to say on constraints, but as you might imagine this is not the right place. To find more on constraints check User guide constraint section.

Parameters can have several different scopes, to read more on this check the User guide parameter section .

The next annotation on the source is @InjectParameterErrors. This annotation purpose is to make the possible parameter input data errors available on the Stage. These errors are detected by DIF taglibs and can be injected on your business logic for execution flow redirecting. We'll see a basic example in a minute.

The last annotation is @OnSubmit. Take notice of it's usage scope: I'm using it on a method. It marks the method for execution in response to an HTML-originated "onsubmit" event. It has an attribute named "value" whose name you don't need to specify (it is the default attribute name, so Java knows what you mean) and whose value (odd thing to write!) is the name of the form that will fire the "onsubmit" event.

This is pretty much of the annotations stuff! Let's get to the method source.

The first method (public Map<String, String> getSexOptions()) is just an auxiliary method I will need on my JSP. It just returns a java.util.Map object with the two sexes discriminated. No big deal.

The second method (public ViewObject onSubmit()) is the method that will be executed after the "onsubmit" event and is my processing method. Here I'm taking advantage of DIF's parameter validation mechanism and I'm using the @InjectParameterErrors-annotated attribute to check if I have consistent data and if I'm able to proceed. If I have good data I simply store it a JavaBean, and set it on the execution context as a stage result. To do so I simply call the following method:

public void addStageResult(String resultName,Object resultValue)

You can see the javadoc for the method here.

Later on, on my response view, I will be able to retrieve the JavaBean from my response.

On with the method's source. The last step is to return some view for DIF's Presentation Layer to render. Remember I defined a @View-annotated attribute before? Now I will use it as the method's return. I had good data, did my processing (which here was just store the data in a JavaBean), set my stage results and returned my success view. That's all to it! But wait! What if I had had bad data? No problem! I simply return null and DIF does the rest for me. How? Well, I declared a default view (PersonalData.jsp). When processing my request DIF will notice that I "forgot" to return a nice view and will put a safety net underneath me. That is, will render the default view who will notice I have errors on my parameters and warn me about it.

So, that's all to it, as explanations are concerned on the Stage. I will just give you the JavaBean source but will not explain nothing there (there's nothing to explain, after all!).

public class SurveyBean implements Serializable {
    
    private static final long serialVersionUID = 1178787308521842639L;

    private String name;

    private Long age;

    private Boolean married;

    private String sex;

    public Long getAge() {
        return age;
    }

    public void setAge(Long age) {
        this.age = age;
    }

    public Boolean getMarried() {
        return married;
    }

    public void setMarried(Boolean married) {
        this.married = married;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

JSPs

The last part of this tutorial step will show you the JSPs I use in this tutorial. As you might recall from the Application Definition we will have two JSPs: one with form and another to echo the data. You should create the JSPs on the "/src/main/webapp" folder.

Before you proceed with the tutorial you might want to review EL (Expression Language) of the JSP2.0, since I will use it a lot. If you wish to do it please follow this link.

Let's start with the most complex one: the "PersonalData.jsp". I'll start by showing you the source and then I'll explain it to you.

PersonalData.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="/WEB-INF/dif-core.tld" prefix="dif"%>
<dif:document>
    <h1>${messages.title}</h1>
    <dif:parameterErrors />
    <dif:form name="personal">
        <dif:textField id="name" label="${messages.name}" />
        <br />
        <dif:textField id="age" label="${messages.age}" />
        <br />
        <dif:checkBoxField id="married" label="${messages.married}" />
        <br />
        <dif:comboField id="sex" label="${messages.sex}" options="${stage.sexOptions}" />
        <br />
        <input type="submit" />
    </dif:form>
</dif:document>

Hopefully I don't have to explain you the first line. So I'm getting to the second line immediately. Here it is:

<%@ taglib uri="/WEB-INF/dif-core.tld" prefix="dif"%>

Here I'm telling the application server that I wish to use a tag library named "dif-core" whose descriptor is on the WEB-INF folder and that I'll precede the tag names with the prefix "dif". There's some magic going behind the scene, since if you check your WEB-INF folder you won't find the aforementioned file. No problem! Maven knows you'll need it and will put it on the right place for you when it prepares the app for deploying. On to the tags.

The first tag on the JSP is:

<dif:document> ... </dif:document>

This tag wraps everything else on the JSP. It takes care of page context, CSS and JS inclusion, so it really does a lot of stuff for you.

Before proceeding to the next tag I must tell you about messages. DIF let's you customize the text you write on a page. You can have a file containing key/value pairs with the messages texts and include it on your page. This feature might be very useful for internationalization of your web app. To use this convenient capability there are some conventions you must follow:

  1. The file must be named <StageName>.messages
  2. The file must be placed on an hierarchical subfolder under src/main/resources/messages that must have the same depth than the DEM element that it is bound to.
  3. Exception to the rule before: the Stages messages must be put on the Service folder. That is, the folder hierarchy stops on the Service.
  4. The file must be a set of entries of the form: key=value

This might be clearer if I show you examples.

Here's the tree of my src/main/resources folder.

`---resources
    ¦
    `---messages
        ¦      
        `---demoprovider
            ¦ 
            `---surveys
                ¦
                `---personalinfo
                        PersonalData.messages

As for the file structure, here it is my PersonalData.messages:

title=Personal Information Survey
name=Full Name
age=Years of Age
sex=Sex
married=Married
success=Your survey has been successfully completed.
thanks=Thank you

Just remember that messages are inherited, so if you had a DemoProvider.messages file on the messages/DemoProvider folder you could use those messages on your Stage.

To access the messages you just have to do two things:

  1. Remember that de <dif-document> tag put an object containing the messages on the page context (so it's available to you!). The object's name is...messages, what else it could be?
  2. Fetch the message using the proper EL syntax.

I'll show you an example in case you missed on the JSP source above.

 <h1>${messages.title}</h1>             

This line is fetching the message whose key is "value" from the message object and rendering it as an HTML level-1 heading.

On with the tags. The next one to show up is:

<dif:parameterErrors />

This is a no-attributes tag that defines the place where the user will see the parameter error warnings. I want it to stand out so it won't get missed by the user, so I place the tag right under the page heading. DIF's presentation layer detects if it should render anything and it just does so if there are errors on the parameters.

The following tag is this:

<dif:form name="personal"> ... </dif:form> 

This tag naturally helps you defining an HTML form. It wraps the form fields and has a mandatory attribute: the "name". This name will be used to bind the form field data to the Stage's @Parameter-annotated attributes, so be EXTREMELY cautious on this.

There are some form elements available for you as well. Here's the text input field tag:

<dif:textField id="name" label="${messages.name}" />

As you can see you have two attributes here: the "id" (which will bind the field value to @Parameter-annotated attribute) and the "label" which is the text that will be rendered before the field.

I need to use a check box on my form as well. So I'll use this tag:

<dif:checkBoxField id="married" label="${messages.married}" />

It works exactly as the text field except that the generated widget is a check box. No big deal but very useful!

The last tag I'm going to show you is the combo box. This is the code:

<dif:comboField id="sex" label="${messages.sex}" options="${stage.sexOptions}" />

Once again you have the "id" and "label" attributes, and also a new one: "options". As you might be thinking, you need some way to inject the options in the combo box and that way is through the "options" attribute. Notice that I'm doing $stage.sexOptions. Can you tell me what I'm doing here? Well, I'm combining the power of DIF and of JSPs EL. DIF will make the Stage accessible for you on the page context on an object named "stage" and you can

Note that all through these tags I have been using the messages object and I'm accessing it the EL-way. That is, I can have a method named getXXX() on my Stage and access the method on my view. To do it, I just need to skip the get part of the method's name and use the EL syntax to "invoke the method". Now you know why I put an auxiliary method on the Stage.

The last thing to do on the form is to put a submit button. DIF will know what to do next! (Hint: remember the @OnSubmit annotation?)

I have one more tag to show you. But first I will present you the code of our second page where the app gives the user some feedback.

Success.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="/WEB-INF/dif-core.tld" prefix="dif"%>
<dif:document>
    <h1>${messages.title}</h1>
    <h2>${messages.success}</h2>
    <p>${messages.thanks}: ${difresponse.stageResults.survey.name}</p>
    <dif:stageLink stageID="homestage"/>
</dif:document>

There are just two new things on this source. Well, actually is more "one-and-a-half". Look here:

${difresponse.stageResults.survey.name} 

This is the "half new thing". If you've been following me you'll understand what's happening after the first dot. Exactly! I'm accessing the value of the "name" field on a stored stage result with "survey" as id. That's pretty close to what I did with the combo box options above.

The new thing is that DIF will put a response object on the page context that you can access to retrieve several interesting things. Well, after all this might not be so surprising at all...after all this long explanation you must already be anticipating almost everything I'm about to say. So, this isn't really new stuff...I'll rephrase what I said above: "There is just one new thing on this source" (two half-new things = one new thing)! Exactly the same thing that happens with DIF concerning the work you must do: before you had a lot of it, with DIF you have much less!

So now you know a lot and probably are willing to apply it to your own ideas! Go ahead, practice makes perfect!

You can download the porject source here: TODO: Add a link to download the full source code here.

Advance to Deploying the application