Developing Great Software

Showing posts with label html. Show all posts
Showing posts with label html. Show all posts

Thursday, April 28, 2011

The NetBeans 7 Wicket Plugin

Geertjan Wielenga has released an updated version of the Wicket Plugin for NetBeans 7.  For us Wicket fanatics this is indeed great news. The plugin adds some really nice enhancements and productivity features to the NetBeans platform and, when taken in total, in my opinion makes NetBeans the undisputed best platform for Wicket development.

If you haven’t done so already I urge you to download this plugin from the NetBeans plugin portal and install it into NetBeans 7. For those of you not familiar with installing plugins from the NetBeans portal, here are the steps you should follow:

Installing The Wicket Plugin

1. Go to http://plugins.netbeans.org/plugin/3586/wicket-1-4-support and click the Download button to download the zip file to your computer. Once it is downloaded extract all the files. On Windows you can extract the files by right clicking the file with your mouse and selecting Extract All.

2. Start up NetBeans if it isn’t already and select Tools | Plugins from the main menu. This will open the Plugin window.

3. Select the Downloaded tab and then select the Add Plugins button.

4. Navigate to the folder where you the extracted files reside, select all 3 files and then select the Open button.

2011-04-28 19h44_53

5. Select the Install button and NetBeans will install the plugin modules after which you will be prompted to restart NetBeans. Please, restart NetBeans.

Create A Wicket Project

Lets explore some of the productivity enhancing features that the Wicket plugin provides. We’ll start first by creating a new Wicket project.

1. From the main menu select File | New Project. Then, select Java Web from the Categories panel and select Web Application from the Projects panel and then select Next.

2. Enter any name you like for the Project Name and select Next.

3. Select Apache Tomcat 7.0.11 for the Server (if you prefer, you can also select GlassFish 3.1) and Java EE 6 Web for the Java EE Version and select Next.

4. In the Frameworks step you can see that there is an option to select Wicket as the framework you want to use in your application. This is the 1st and most obvious contribution that the Wicket plugin provides, easy integration of Wicket into a NetBeans Java Web project. When you select Wicket the Plugin provides you with numerous configuration options such as the name of the Wicket filter and the URL pattern, for instance. For our run through we are going to accept all the defaults.

2011-04-28 20h01_37

5. Select Wicket and then select Finish. NetBeans will now generate a starter Wicket application.

Fully expand the newly created project in the Projects panel.

2011-04-28 20h13_02

As you can see from the above, the Wicket plugin created a complete Wicket starter project, libraries and all. It also created numerous Wicket components: BasePage, FooterPanel, HeaderPanel and HomePage as well as the required Application.java class. The plugin also configured web.xml according to the configuration parameters that we chose in the Frameworks step.

Run The New Wicket Application

Now, from the main menu select Run | Run Main Project to run the newly created application. As you can see from the rendered page in the browser, the starter project, though trivial, is rather nice - it has a header section, a middle section for content and a footer section, too.

 

2011-04-28 20h21_38

You will, of course, want to modify the starter project to match your own application’s requirement but because the starter project uses Wicket Markup Inheritance you will be able to do this rather easily.

The Starter Project

Lets explore the components that the plugin generated for us.

Open the BasePage component by double clicking on either BasePage.html or BasePage.java. When you click on either, both files will open. This behavior is contributed by the Wicket plugin and I find it extremely convenient.

Now, lets look at BasePage’s markup and java implementation.

<!DOCTYPE html> 
<html xmlns:wicket="http://wicket.apache.org"> 
    <head> 
        <meta charset="UTF-8"> 
        <meta name="description" content="Put your description here!" /> 
    <wicket:head> 
        <wicket:link> 
            <link rel="stylesheet" type="text/css" href="style.css"/> 
        </wicket:link> 
    </wicket:head> 
</head> 
<body> 
    <header wicket:id="headerpanel" />
    <section class="content_container"> 
        <wicket:child/> 
    </section> 
    <footer wicket:id="footerpanel" /> 
</body> 
</html>
package com.myapp.wicket;           

import org.apache.wicket.markup.html.WebPage;

/** 
 *
 * @author Jeff
 * @version 
 */

public abstract class BasePage extends WebPage {

    public BasePage() { 
        super(); 
        add(new HeaderPanel("headerpanel", "Welcome To Wicket")); 
        add(new FooterPanel("footerpanel", "Powered by Wicket and the NetBeans Wicket Plugin"));
    } 

}

BasePage.html’s header contributes style.css, which is a packaged resource that resides in the same package as the BasePage component. By using wicket:head and wicket:link tags, Wicket will be able to resolve the reference to style.css and include it in the rendered page.

In the body of the page there are place holders for the header and footer panels. There’s also a wicket:child tag declared which will allow any page that inherits from BasePage to contribute its content to the page. This is what Wicket calls ‘Markup Inheritance’. I’ll show you how this is used when we look at the HomePage component later in the article.

BasePage.java’s implementation is what you would expect to find considering the markup we just explored. BasePage derives from WebPage and after calling into its super class BasePage’s contrcutor adds the HeaderPanel and FooterPanel components to the page. The constructors for both of these components allows you to add the text that will be displayed for each as their second parameters.

Now, lets look at HomePage’s markup and java implementation.

<!DOCTYPE html> 
<html xmlns:wicket="http://wicket.apache.org"> 
    <head> 
        <meta charset="UTF-8"> 
    <wicket:head> 
        <title>Wicket Example</title> 
    </wicket:head> 
</head> 
<body> 
    <wicket:extend> 
       <h1 wicket:id="message">This gets replaced</h1>
    </wicket:extend> 
</body> 
</html>
package com.myapp.wicket;           

import org.apache.wicket.markup.html.basic.Label;

public class HomePage extends BasePage {

    public HomePage() {
        add(new Label("message", "Hello, World!"));
    }

}

Again, there are no surprises here but one item needs to be elaborated on. HomePage derives from BasePage and as I had mentioned, HomePage uses Markup Inheritance to contribute its markup to the page. It will attach its markup to the h1 tag which is sandwiched between the opening and closing wicket:extend tags. This is how Wicket Markup Inheritance works and it is a very powerful technique to use when you want to compose pages that have the same layout and appearance.

I’ll let you explore HeaderPanel and FooterPanel on your own though these also will be what you would expect as both implementations are derived from Panel.

Now lets explore some of the other productivity enhancements that the Wicket plugin provides.

Creating A New Page And A New Panel

To create a new Page, right click the package which currently contains our project’s components and select New | Wicket Page. Enter any name for the Page and select Finish. Two files, one html and one Java, will open in the browser.

Creating a new Panel is much like creating a new Page. Right click the package which currently contains our project’s components and select New | Wicket Panel. Enter any name for the Panel and select Finish. Two files, one html and one Java, will open in the browser.

Exploring Components With Navigator

The plugin adds what I call ‘Wicket Sense’ (my term for a lack of a better one) to the NetBeans Navigator. To see this in action, in the editor select the BasePage.html file and if it isn’t already, open the Navigator and select Wicket Tags from its list of views.

As you can see, the Navigator displays all the elements that include wicket:id attributes in their tags. Now switch editor views to BasePage.java and again, notice how the Navigator has identified all the Wicket components in the Java code.

Your will really appreciate Navigator’s Wicket Sense when you are dealing with large Java and markup files.

Jump To Implementation

Another nice feature that the plugin adds is the ability to jump to the Java implementation from within the markup file. In HomePage.html, hold down the control key and hover the mouse over the ‘message’ wicket:id value. An underline will appear and if you now click on ‘message’ the editor will switch views to the Java implementation, opening the file if it isn’t currently open in the editor.

The plugin doesn’t currently support jumping to the markup page from the implementation file but maybe a future release of the plugin will provide this feature.

Much Thanks And Appreciation

Geertjan deserves our thanks and he earns our appreciation for all the effort he has put into this plugin. In my opinion, the plugin empowers NetBeans to provide a level of support for Wicket development that no other IDE can currently match.

Geertjan, great job and thank you!

Well, that’s it for now but remember, busy hands are happy hands, so get going and explore this fabulous plugin and all its great features. Happy coding!

Wicket, Web Services, NetBeans And GlassFish

A reader recently emailed me and wanted to know about implementing a Wicket application within a Web Service environment.

I have not come across any reference where Wicket has been implemented
within a web service environment. None of the books I have read on
Wicket have addressed this area to my knowledge. I am wondering if you
have any insight as to how this would work.

The reader is expressing a very common misconception that a lot of developers have and that misconception is that you somehow have to integrate your Web Services into your Web application. Part of my response to the reader was:

“How you expose your web services has nothing to do with Wicket meaning you don't integrate your web services with wicket.”

Additionally, I went on to say:

“All you need is to create web services on glassfish (it has built in support for web services and Netbeans tooling makes this just so simple). If a client, whether your Wicket application or a paid subscriber for instance, needs to consume your web services it will consume the wsdl files produced when you created the web services.”

What I was trying to express to the reader is that Wicket is just a Web framework and not a Web Services provider. Wicket writes HTML to the browser and that’s about it. Wicket Web applications, however, can consume Web services, either those on the same server the Web application is running on or located on different servers. But Wicket itself doesn’t provide any means to consuming Web services - for that you use Java API for XML Web Services (JAX-WS).

I promised the reader that if I had the time I would write an article demonstrating how this is done which is the purpose of this article. So lets get started.

The remainder of this article assumes you have installed NetBeans 7 as well as the NetBeans Wicket plugin. If you haven’t, please do so now.

NetBeans, GlassFish v3.1 and JAX-WS

NetBeans 7 comes bundled with GlassFish v3.1 and GlassFish comes with Metro 2.1 as its SOAP Web Services provider. Metro 2.1 implements the JAX-WS specification. The synergy between Web Services, NetBeans and GlassFish is provided by the tooling built into NetBeans, which makes authoring and deploying your Web Services on GlassFish very easy, as we shall see later in this article.

When you create a Web Service you first have to decide how you want to package it (what type of application you will use to host your Web Service). You have 2 options:

1. JavaEE EJB Module project – this option should be used if your Web Services require access to EE containers. Web Services in this context are generated as Stateless SessionBeans. If your Web Service needs access to your database, for instance, you can achieve this using the @PersistenceContext annotation within your Web Service which will allow you to access your database via JPA.

2. Package in Web container – this option should be used if your Web Service doesn’t require access to other EE containers.

In this article I won’t actually cover accessing a database because I want to keep it simple but I will use a JavaEE EJB Module project and you can, if you chose, explore this later on your own by creating a Web Service method to access your own database.

Create A Web Service Project

1. If you haven’t already, fire up NetBeans and select File | New Project which will open the New Project window.

2. Select Java EE from the Categories panel and select EJB Module from the Projects panel and select Next.

3. Enter any valid project name you like in the Project Name text box. I am naming mine ‘EJBWebServicesAndWicketTutorial’. Select Next.

4. Select GlassFish Server 3.1 from the Server drop down list and make sure that Java EE 6 is selected in the Java EE Version drop down list. Select Finish to generate the project.

Create A Web Service

1. Right click the project node for the EJB project in the Projects window and select New | Web Service. This will open the New Web Service window.

2. Enter CalculatorWebService for the Web Service Name. Make sure that the Create Web Service from Scratch option is selected. Note that because our project is an EJB the Implement Web Service as Stateless Session Bean option is automatically selected for us and cannot be changed. Enter WebServices as the Package name and select Finish. NetBeans will generate your Web Service Java class in the WebServices package.

3. I will use a simple method for our Web Service that returns the sum of two integers. Replace the content of CalculatorWebService.java with the following:

package WebServices;

import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.ejb.Stateless;

/**
 *
 * @author Jeff
 */
@WebService(serviceName = "CalculatorWebService")
@Stateless()
public class CalculatorWebService {

    /**
     * Web service operation
     * @param i int
     * @param j int
     * @return  the sum of i + j as int
     */
    @WebMethod(operationName = "add")
    public int add(@WebParam(name = "i") final int i, 
    @WebParam(name = "j") final int j) {
        return i + j;
    }
}

From the above code you can see that the CalculatorWebService class is decorated with both @WebService and @Stateless attributes which is what you would expect. Also note that the add method is decorated with the @WebMethod attribute and that each of its parameters, i and j, are decorated with the @WebParam attribute.

I didn’t hand-code this though I could have. NetBeans can generate a Web method with all the correct attributes for you. If you select Design View and click the Add Operation button, NetBeans will present you with its Add Operation window that allows you to add a new Web Service method with all the proper attributes. I’ll leave this as an exercise that you can explore later on your own.

Testing The CalculatorWebService add Method

NetBeans tooling makes testing Web Services a snap so lets do that now to insure that our add service works as expected:

1. In the Project panel right click the Web Services node (not the WebServices package) and select Test Web Service which will open your browser and display the following

2011-04-28 10h23_51

2. Click the WSDL File link and save the URL somewhere (like Windows NotePad, for instance) and then page back to the above. We will use the URL in our Web Services client application, which we will build later on in the article.

3. Enter 4 in the first input field and enter 5 in the second input field and then click add. Your browser will then display the following

2011-04-28 10h30_27

As you can see from the above, the method correctly calculated and returned the sum of our two numbers. If you scroll down the browser page you can see the packaging for both the SOAP request and the SOAP response. Repeat this a few time with different sets of numbers.

We now have a working Web Service that can be consumed by any client that can consume a Web Service. Note how the Web Service we just built has no connection at all with Wicket – our project doesn’t even include the Wicket framework. Remember, Web Services provide a service whereas Wicket applications render HTML to the browser.

Now we know that our method works so lets create a Wicket application that will consume the Web Service. I’ll keep this simple and I assume that you have already installed the latest release of the Wicket plugin for NetBeans 7.

Create a Wicket Application

1. In NetBeans select File | New Project and select Java Web from the Categories panel and Web Application from the Projects panel. Enter any name you like for the Project Name, select Set As Main Project and select Next.

2. For Server select GlassFish Server 3.1 and for Java EE Version select Java EE 6 Web and select Next.

3. For Frameworks select Wicket and select Finish. NetBeans along with the Wicket plugin will generate a Wicket starter application project that includes the Wicket libraries. Also generated by the Wicket plugin are Wicket components for HomePage, BasePage, HeaderPanel, FooterPanel as well as the required Application.java and configuration files.

Now that we have a Wicket application we will use NetBeans to easily configure it to consume the Web Service we created previously.

Consuming Our Web Service

1. In the Projects panel right click the Web applications project node and select New | Web Service Client. This will open the New Web Service Client window.

2. Select WSDL URL and enter the URL that you saved previously when you tested the Web Service.

3. Enter a package name and make sure that JAX-WS Style is the selected option for Client Style. Select Finish. NetBeans will generate a Web Service Reference for us in the Web Service References folder.

Our Web application is now configured to consume the Web Service we previously created. Notice that in the above we configured our Web application using the URL that points to the Web Service’s WSDL. We could have used a project reference instead but I used the URL to emphasize that you can consume any Web Service running on any server, yours or some other, as long as you have access to its WSDL URL.

Now lets actually use the Web Service in our Wicket application.

1. In the Projects panel double click on the HomePage.html file. Notice how NetBeans opens it as well as the HomePage.java file. This behavior, among others such as generating a starter project, is a contribution of the NetBeans Wicket plugin.

2. Replace all the content in HomePage.html with the following:

<!DOCTYPE html> 
<html xmlns:wicket="http://wicket.apache.org"> 
    <head> 
        <meta charset="UTF-8"> 
    <wicket:head> 
        <title>Wicket Example</title> 
    </wicket:head> 
</head> 
<body> 
    <wicket:extend> 
       <h1 wicket:id="message">This gets replaced</h1>
       <form wicket:id="form" >
           <div wicket:id="feedbackpanel" />
           <input type="text" wicket:id="input1" /> + <input type="text" wicket:id="input2" /> = <span wicket:id="result" /><br/>
           <input type="submit" />
       </form>
    </wicket:extend> 
</body> 
</html>

From the above you can see that our markup is quite simple - we create a simple form with two text fields and a submit button.

Now, lets consume the add Web Service method.

1. Select the HomePage.java file and from the Projects panel and fully expand the Web Service References folder. Drag and drop the add method anywhere into the HomePage.java file and NetBeans will generate the call to our Web Service method for us. Rather than implement the rest of the code yourself you can replace the code in HomePage.java with the following

/*
 * HomePage.java
 *
 * Created on April 28, 2011, 6:30 AM
 */

package com.myapp.wicket;           

import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.CompoundPropertyModel;

public class HomePage extends BasePage {
    
    private int input1 = 0;
    private int input2 = 0;
    private int result = 0;

    public int getInput1() {
        return input1;
    }

    public void setInput1(int input1) {
        this.input1 = input1;
    }

    public int getInput2() {
        return input2;
    }

    public void setInput2(int input2) {
        this.input2 = input2;
    }

    public int getResult() {
        return result;
    }

    public void setResult(int result) {
        this.result = result;
    }
    
    public HomePage() {
        add(new Label("message", "Enter 2 ints!"));

        Form<HomePage> form = new Form<HomePage>("form", new CompoundPropertyModel<HomePage>(HomePage.this)){

            @Override
            protected void onSubmit() {
                super.onSubmit();
                // Call the add web service method to calculate the result
                result = add(input1, input2);
            }
            
        };
        
        form.add(new FeedbackPanel("feedbackpanel"));
        form.add(new TextField<String>("input1"));
        form.add(new TextField<String>("input2"));
        form.add(new Label("result"));
        add(form);
    }

    private static int add(int i, int j) {
        webservices.CalculatorWebService_Service service = new webservices.CalculatorWebService_Service();
        webservices.CalculatorWebService port = service.getCalculatorWebServicePort();
        return port.add(i, j);
    }

}

In our java implementation we add the two text  fields to the form and the the form to the page. We override the form’s onSubmit method in which we call our Web Service method and assign its return value to result. When Wicket renders the page the page will display the result. Lets try it. Run the Web application and you should see the following

2011-04-28 11h32_22

Enter a valid numeric/integer value for both input fields and select Submit. The page will render with the result.

2011-04-28 11h34_05

Here is the result I get when I enter 10 and 14. The result, 24, is rendered back to the page. If you enter a non numeric value you will get an error message.

What We’ve Learned

As the examples here have demonstrated, an application that publishes Web Services is totally disconnected from any application that consumes its services. In our case, the consumer is a Wicket application. Wicket renders HTML and in our case it renders the result of calling our Web Service.

Our Web Service implementation knows nothing about any client application that may use its services. The client application consumes the Web Service via the WSDL.

In addition, NetBeans and its GlassFish tooling really makes both publishing and consuming Web Services ridiculously easy and the NetBeans Wicket plugin, with its ability to create a starter project as well as Wicket Pages and Panels is a great productivity booster.

I hope you have enjoyed this little walk-through of publishing and consuming Web Services with NetBeans, GlassFish, Wicket and the NetBeans Wicket plugin. Please feel free to leave a comment or a question.

Thursday, March 31, 2011

Java EE6 & Wicket - Article #6 – A Wrap Up

Welcome to the 6th in a series of detailed articles on Java EE6 & Wicket. If you haven’t already, please read the following previous articles before continuing.

  1. http://jeff-schwartz.blogspot.com/2011/03/java-ee6-wicket.html
  2. http://jeff-schwartz.blogspot.com/2011/03/java-ee6-wicket-article-1-requirements.html
  3. http://jeff-schwartz.blogspot.com/2011/03/java-ee6-wicket-article-2-creating.html
  4. http://jeff-schwartz.blogspot.com/2011/03/java-ee6-wicket-article-3-generating.html
  5. http://jeff-schwartz.blogspot.com/2011/03/java-ee6-wicket-article-4-adding-jpa.html

In this, the 6th and final article in this series, we will examine the code, focusing on the integration we provided for consuming the EJB in our HomePage. I will also discuss some best practices that I’ve used here, especially pertaining to Wicket components and project structure.

Consuming EJB In Wicket

In article #3 we added the JavaEE Inject jars to the GuestBook project. JavaEE Inject is a Wicket module that provides integration through Java EE 6 resource injection and supports three annotations:

  1. @EJB
  2. @PersistenceUnit
  3. @Resource

With JavaEE Inject any Wicket application running in a Java EE6 container can consume the above 3 types of JavaEE resources. Before an application can use them, however, its WebApplication class method init must be overridden to add the JavaEEComponentInjector into Wicket’s request cycle. The code is simple as shown below:

@Override
    protected void init() {
        super.init();
        addComponentInstantiationListener(new JavaEEComponentInjector(this));
    }

What we are doing in the above code is calling Wicket’s Application class method addComponentInstantiationListener with a reference to a JavaEEComponentInjecter object which the JavaEE Inject module provides. addComponentInstantiationListener adds the JavaEEComponentInjector object to its lists of component instantiation listeners that it maintains.

With the JavaEEComponentInjector now maintained whenever a Wicket component is instantiated, JavaEEComponentInjector will scan the component for one of the above three annotations and injects their associated resources into the component.

There is one limitation, though, imposed by JavaEE Inject and that is it can only inject resources into a component that is a subclass of WicketPage. This  has implications on the modularity of our code in that we can’t directly reference EJB methods, for instance, directly in classes that aren’t derived from WebPage. Or can we? Well, we can and I will show you how we did it in GuestBook.

Techniques For Using JavaEE Inject Resources Outside Of WebPages

GuestBook uses an instance of a DataView to display the list of names of its visitors. A DataView requires a pseudo model of type IDataProvider<T> dataProvider to provide the data that it displays and GuestDataProvider serves that purpose. GuestDataProvider uses methods from our session bean to access the data in the guest table but it, like HomePage, is declared in its own file so how can it access the session bean and call into its methods?

The solution was to create the following interface that GuestDataProvider implements:

public interface IEjbDataProvider<T> extends IDataProvider<T> {
    AbstractFacade<T>  getFacade();
}

GuestDataProvider is declared as abstract because it doesn’t actually implement getFacade which is defined as returning an instance to AbstractFacade. Instead, GuestFacade relies on its subclasses to provide the method’s implementation.

In the HomePage constructor we create an instance of a GuestDataProvider and override its getFacade method by returning the reference to our session bean.

public class HomePage extends BasePage {

    @EJB(name = "GuestFacade")
    private GuestFacade guestFacade;

    public HomePage() {
        super();

        add(new FeedbackPanel("feedback"));

        /*
         * A loadable and detachable model whose sole purpose is to always
         * return a new Guest object when its load method is called.
         */
        LoadableDetachableModel<Guest> newGuestLoadableDetachableModel = new LoadableDetachableModel<Guest>() {

            @Override
            protected Guest load() {
                return new Guest();
            }
        };

        /*
         * The guestForm uses a nested model. The outer model is a compound property
         * model and the inner model is a light weight loadable and detachable model.
         */
        Form<Guest> guestForm = new Form<Guest>("guestform", new CompoundPropertyModel<Guest>(newGuestLoadableDetachableModel)) {

            @Override
            protected void onSubmit() {
                Guest guest = getModelObject();
                guestFacade.create(guest);
                setModelObject(new Guest());
                guest = new Guest();
            }
        };

        /*
         * Add the custom NameTextField compent for
         * first and last name to the form, nesting each
         * in a FormComponentFeedbackBorder for displaying
         * data entry errors.
         */
        guestForm
                .add(new FormComponentFeedbackBorder("firstNameBorder")
                .add(new NameTextField("firstName")));
        guestForm
                .add(new FormComponentFeedbackBorder("lastNameBorder")
                .add(new NameTextField("lastName")));
        add(guestForm);

        GuestDataProvider gdp = new GuestDataProvider() {

            @Override
            public AbstractFacade<Guest> getFacade() {
                return guestFacade;
            }
        };

        /*
         * When dealing with potentially large lists of data it is
         * better to use a DataView whose constructor takes a data
         * provider as its second parameter.
         */
        DataView<Guest> guestListView = new DataView<Guest>("namelist", gdp) {

            @Override
            protected void populateItem(Item<Guest> item) {
                Guest guest = item.getModelObject();
                item.add(new Label("name", guest.toString()));
            }

        };

        add(guestListView);

    }
}

This demonstrates that though JavaEE Inject places restrictions on where we can inject resources there are simple patterns that we can employ to overcome them.

Wicket Models Put To Best Use

HomePage also uses loadable/detachable models for both the form and the list of visitor names it displays. When Wicket completes its request cycle the components containing them will not contribute any model data to the serialization of the page.

Though I won’t go into detail here, understanding and mastering Wicket models is a critical component of your Wicket education. If you don’t know the difference between static and dynamic models or you aren’t familiar with loadable/detachable models you can read my article here to get up to speed on this subject.

Components

Now, lets talk a bit about Wicket components and some ideas that I’d like to share with you.

Whenever I develop a Web application I like to encapsulate business rules so that they can be reused. Presentation components are a prime target for encapsulating business rules, especially if they are used more than once on a page or on more than one page. Business rules encompass issues like requiring the user to enter a value for an input field, min and max values, etc.

Some frameworks make extending their presentation components more difficult than one would imagine. On the other hand, this is one area where Wicket shines – Wicket’s components are strikingly easy to extend and to imbed business rules in.

In article #1 we expressed the business rules for GuestBook as follows:

  • Limit the number of characters our visitors can key in for their first and last names to a maximum of 45 characters each.
  • Both first and last name are required.

GuestBook uses NameTextField, a subclass of TextField, to encapsulate and enforce its business rules.

public class NameTextField extends TextField<String>{

    /**
     *
     * @param id
     * @param model
     */
    public NameTextField(String id, IModel<String> model) {
        super(id,model);
        setRequired(true);
    }

    /**
     *
     * @param id
     */
    public NameTextField(String id) {
        this(id,null);
    }

    @Override
    protected void onComponentTag(ComponentTag tag) {
        tag.put("maxlength", "45");
        tag.put("size", "55");
        super.onComponentTag(tag);
    }


}

Since both first name and last name must enforce the same requirements on the user it makes sense to encapsulate the logic in one place. In the above code we set the component’s required flag to true and we override the onComponentTag method to output the ‘maxlength’ and ‘size’ attributes for the input tag.

This is a prime example of applying the ‘Don’t Repeat Yourself’ (DRY) principle in action and Wicket, to its credit, makes this an incredibly easy process.

Now a word or two on structuring your code.

Project Structure

One of the things I really hate is dealing with a project which just dumps everything into a single package whose name provides absolutely no insight as to the purpose of the code contained in it. Bad! Bad! Bad!

In GuestBook, package names provide useful insight as to the purpose of the code they contain. The packages also serve to layer the project’s structure by areas of concern, namely entities, session beans and Wicket which it further sub groups into components and data providers.

Some Final Thoughts

Well that just about wraps things up for this series but before we say goodbye I’d like to extend my thanks to all the developers and contributors who have made Java, Wicket and its infrastructure of contributed libraries and NetBeans the productive resources they are for us.

I hope you have enjoyed reading this series and following along with me as much as I have enjoyed sharing my time with you.

Please feel free to leave your comments for any of the articles in this series and I will try to find the time to respond to them all.

May all your days coding be happy and productive ones.

Wednesday, March 30, 2011

Java EE6 & Wicket - Article #5–Building Out The Guest Book Web Application Using NetBeans

Welcome to the 5th in a series of detailed articles on Java EE6 & Wicket. If you haven’t already, please read the following previous articles before continuing.
  1. http://jeff-schwartz.blogspot.com/2011/03/java-ee6-wicket.html
  2. http://jeff-schwartz.blogspot.com/2011/03/java-ee6-wicket-article-1-requirements.html
  3. http://jeff-schwartz.blogspot.com/2011/03/java-ee6-wicket-article-2-creating.html
  4. http://jeff-schwartz.blogspot.com/2011/03/java-ee6-wicket-article-3-generating.html
  5. http://jeff-schwartz.blogspot.com/2011/03/java-ee6-wicket-article-4-adding-jpa.html

In this, the 5th article in this series, we will complete the implementation of the GuestBook Web application. So lets get started.

Modifying The Generated Markup And Code

If you haven’t already, fire up NetBeans because we are going to make a few changes to the generated code so that our GuestBook’s home page will look like the image in article #1. In order to do that we will compose the HomePage using Wicket Markup Inheritance.

Our HomePage displays a Wicket logo which you can download here. Place the logo  in the com.myapp.wicket package.

Next, we need to make a few changes to the generated code. Create a new HTML file in the com.myapp.wicket package and name it BasePage.

  1. Right click on the com.myapp.wicket package, select New | Other to open the New File window
  2. Select Web in the Categories panel and then select HTML in the File Types panel and click the Next button.2011-03-30 08h45_57
  3. Enter BasePage for the HTML File Name and click the Finish button. NetBeans will generate the BasePage.html file and open it in the editor.

Replace the generated markup with the following markup and save the file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta name="description" content="A guest list of the rich and famous written in Java and Wicket">
</head>
<body>
<div wicket:id="headerpanel"></div>
<wicket:child/>
</body>
</html>

Replace all the code in com.myapp.wicket.BasePage.java with the following code and save the file:

package com.myapp.wicket;           

import org.apache.wicket.markup.html.WebPage;

/**
*
* @author Jeff
* @version
*/

public class BasePage extends WebPage {

/**
* Construct.
* @param model
*/
public BasePage() {
super();
add(new HeaderPanel("headerpanel"));
}
}

Replace the HTML markup in com.myapp.wicket.HeaderPanel.htm with the following markup and save the file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:wicket="http://wicket.apache.org">
<head><title></title></head>
<body>
<wicket:panel>
<wicket:link>
<img src="Apache_Wicket_logo.png" style="float:left;"/>
</wicket:link>
<h1 style="margin-left: 180px; color: #E9601A; font-style: italic; font-size: 1.5em; font-family: sans-serif; font-weight: bold; line-height: 59px; white-space: nowrap">
<span wicket:id="headerpanneltext">Java EE6 And Wicket EJB Tutorial</span>
</h1>
<hr style="color: #E9601A; background-color: #E9601A; height: 1px;"/>
</wicket:panel>
</body>
</html>

Replace the Java code in com.myapp.wicket.HeaderPanel.java with the following code and save the file:

package com.myapp.wicket;           

import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;

/**
*
* @author Jeff
* @version
*/

public class HeaderPanel extends Panel {

public HeaderPanel(String id)
{
super(id);
add(new Label("headerpanneltext", "Java EE6 And Wicket EJB Tutorial"));
}

}

Replace all the HTML markup in com.myapp.wicket.HomePage.html with the following markup and save the file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<wicket:head>
<title>Guests</title>
<wicket:link>
<link rel="stylesheet" type="text/css" href="style.css"/>
</wicket:link>
</wicket:head>
</head>
<body>
<wicket:extend>
<div>
<div style="margin-top: 20px; padding-left: 15px;">
<h2 style="color:#333333; white-space: nowrap;">Please Sign Our Guest List</h2>
<div wicket:id="feedback"></div>
<form wicket:id="guestform">
<label>First Name:
<span wicket:id="firstNameBorder">
<input wicket:id="firstName" type="text"/>
</span>
</label>
<br/>
<label>Last Name:
<span wicket:id="lastNameBorder">
<input wicket:id="lastName" type="text"/>
</span>
</label>
<br/>
<input type="submit"/><input type="reset"/>
</form>
</div>
<hr style="background-color: #E9601A; color: #E9601A; height: 1px; margin-top: 20px;"/>
<div style="margin-top: 20px; padding-left: 15px;">
<h2 style="color:#333333; white-space: nowrap;">Visitors Who Have Signed Our Guest List</h2>
<div wicket:id="namelist" style="white-space: nowrap;">
<span wicket:id="name" style="font-size: 1.2em; color: #333333;">name</span>
</div>
</div>
</div>
</wicket:extend>
</body>
</html>

Replace all the Java code in com.myapp.wicket.HomePage.java with the following code and save the file:

package com.myapp.wicket;

import com.myapp.wicket.components.NameTextField;
import com.myapp.wicket.dataproviders.GuestDataProvider;
import com.myapp.entities.Guest;
import com.myapp.sessionbeans.AbstractFacade;
import com.myapp.sessionbeans.GuestFacade;
import javax.ejb.EJB;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.validation.FormComponentFeedbackBorder;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.LoadableDetachableModel;

public class HomePage extends BasePage {

@EJB(name = "GuestFacade")
private GuestFacade guestFacade;

public HomePage() {
super();

add(new FeedbackPanel("feedback"));

/*
* A loadable and detachable model whose sole purpose is to always
* return a new Guest object when its load method is called.
*/
LoadableDetachableModel<Guest> newGuestLoadableDetachableModel = new LoadableDetachableModel<Guest>() {

@Override
protected Guest load() {
return new Guest();
}
};

/*
* The guestForm uses a nested model. The outer model is a compound property
* model and the inner model is a light weight loadable and detachable model.
*/
Form<Guest> guestForm = new Form<Guest>("guestform", new CompoundPropertyModel<Guest>(newGuestLoadableDetachableModel)) {

@Override
protected void onSubmit() {
Guest guest = getModelObject();
guestFacade.create(guest);
setModelObject(new Guest());
guest = new Guest();
}
};

/*
* Add the custom NameTextField compent for
* first and last name to the form, nesting each
* in a FormComponentFeedbackBorder for displaying
* data entry errors.
*/
guestForm
.add(new FormComponentFeedbackBorder("firstNameBorder")
.add(new NameTextField("firstName")));
guestForm
.add(new FormComponentFeedbackBorder("lastNameBorder")
.add(new NameTextField("lastName")));
add(guestForm);

GuestDataProvider gdp = new GuestDataProvider() {

@Override
public AbstractFacade<Guest> getFacade() {
return guestFacade;
}
};

/*
* When dealing with potentially large lists of data it is
* better to use a DataView whose constructor takes a data
* provider as its second parameter.
*/
DataView<Guest> guestListView = new DataView<Guest>("namelist", gdp) {

@Override
protected void populateItem(Item<Guest> item) {
Guest guest = item.getModelObject();
item.add(new Label("name", guest.toString()));
}

};

add(guestListView);

}
}

Replace the content of com.myapp.wicket.style.css with the following content and save the file:

body {
white-space: nowrap;
}

.feedbackPanelERROR {
color: red !important;
list-style: circle;
font-weight: bold;
}

.feedbackPanelINFO {
color: green;
list-style: circle;
font-weight: bold;
}

We need to create a properties file in which we will declare the warning messages that Wicket will use when validating the input form on the HomePage.

  1. Right click on the com.myapp.wicket package in the Projects panel and select New | Other to open the New File Window.
  2. Select Other from Categories and select Properties File from File Types and click the Next button.
  3. Enter HomePage for the File Name and click the Finish button. NetBeans will open the properties file in the eiditor.

Add the following content to the the com.myapp.wicket.HomePage.properties file and save the file:

firstName.Required=First Name Is Required. 
    
lastName.Required=Last Name Is Required.

Next, we will add a custom TextField component to the project.

  1. Right click on Source Packages in the Projects panel and select New | Other to open the New File window.
  2. Select Java from Categories and Java Class from File Types and click the Next button.
  3. Enter NameTextField for the Class Name and enter com.myapp.wicket.components for the Package name and click the Finish button. NetBeans will open the NameTextField.java file in the editor.

Replace all the Java code in the NameTextField.java file with the following and save the file:

package com.myapp.wicket.components;

import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;

/**
* A domain specific extension of a Wicket TextField
* that sets the required flag and adds the maxlength=45
* and size=55 attributes to be rendered.
*
* Demonstrates how you can easily extend Wicket
* components to provide domain specific requirement.
*
* @author Jeff
*/
public class NameTextField extends TextField<String>{

/**
*
* @param id
* @param model
*/
public NameTextField(String id, IModel<String> model) {
super(id,model);
setRequired(true);
}

/**
*
* @param id
*/
public NameTextField(String id) {
this(id,null);
}

@Override
protected void onComponentTag(ComponentTag tag) {
tag.put("maxlength", "45");
tag.put("size", "55");
super.onComponentTag(tag);
}


}

Next, we will add an interface to the project.

  1. Right click on Source Packages in the Projects panel and select New | Other to open the New File window.
  2. Select Java from Categories and select Java Interface from File Types and click the Next button.
  3. Enter IEjbDataProvider.java for the Class Name and enter com.myapp.wicket.dataproviders for the Package name and click the Finish button. NetBeans will open the IEjbDataProvider.java file in the editor.

Replace all the Java code in the IEjbDataProvider.java file with the following and save the file:

package com.myapp.wicket.dataproviders;

import com.myapp.sessionbeans.AbstractFacade;
import org.apache.wicket.markup.repeater.data.IDataProvider;

/**
* Extended interface definition of IDataProvider<T> that provides type safe access to session beans.
* Provides the ability to access a session bean in any object.
*
* Use Case: Need to access session in objects other than a Wicket WebPage.
*
* Background - The JavaEEComponentInjector enables Java EE 5 resource injection in Wicket Pages but
* often we need to access to session beans from other objects such as DataProviders and Models. This
* interface supports such a use cases.
*
* Usage
* public class HomePage extends BasePage {
* @EJB(name = "GuestFacade")
* private GuestFacade guestFacade;
* private Guest guest;
*
* public HomePage() {
* super();
* guest = new Guest();
* GuestDataProvider gdp = new GuestDataProvider() {
*
* @Override
* public AbstractFacade<Guest> getFacade() {
* return guestFacade;
* }
* };
*
*
* @param <T>
* @author Jeff
*/
public interface IEjbDataProvider<T> extends IDataProvider<T> {
AbstractFacade<T> getFacade();
}

Next, we will add a Java class to the project.

  1. Right click on com.myapp.wicket.dataproviders in the Projects panel and select New | Other to open the New File window.
  2. Select Java from Categories and select Java Class from File Types and the click the Next button.
  3. Enter GuestDataProvider for Class Name and click the Finish button.

Replace all the Java code in the GuestDataProvider.java file with the following and save the file:

package com.myapp.wicket.dataproviders;

import com.myapp.entities.Guest;
import java.util.Iterator;
import java.util.List;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;

abstract public class GuestDataProvider implements IEjbDataProvider<Guest>{

@Override
public Iterator<? extends Guest> iterator(int first, int count) {
int[] range = {first, count};
List<Guest> guests = getFacade().findRange(range);
return getFacade().findRange(range).iterator();
}

@Override
public IModel<Guest> model(final Guest object) {

final Integer id = object.getId();

LoadableDetachableModel<Guest> ldm = new LoadableDetachableModel<Guest>(object) {
@Override
protected Guest load() {
return getFacade().find(id);
}
};

return ldm;
}

@Override
public int size() {
return getFacade().count();
}

@Override
public void detach() {}

}

The last change we must make is to com.myapp.wicket.Application.java file. Replace all the code in Application.java with the following code and save the file:

package com.myapp.wicket;           

import org.apache.wicket.protocol.http.WebApplication;
import org.wicketstuff.javaee.injection.JavaEEComponentInjector;
/**
*
* @author Jeff
* @version
*/

public class Application extends WebApplication {

public Application() {
}

@Override
protected void init() {
super.init();
addComponentInstantiationListener(new JavaEEComponentInjector(this));
}

@Override
public Class getHomePage() {
return HomePage.class;
}
}

With all these changes in place you should now be able to run the project in your browser.

In the next and last article we will examine the code, focusing on the integration we provided for consuming the EJB in our HomePage. I will also discuss some best practices that I’ve used here, especially pertaining to Wicket components and models. If you don’t know the difference between static and dynamic models or you aren’t familiar with loadable/detachable models you can read my article here to get up to speed on this subject. Stay tuned!

Thursday, November 18, 2010

Screenshots of Love My Vehicle On The Web

A number of years back I had written a desktop software package for tracking and managing the maintenance of vehicles and it was called Love My Vehicle. The software was well received and it managed to attract a rather large & loyal following of paid customers and had won numerous awards from various software rating groups as well as user groups. The application was written for Windows using Microsoft C++ and the MFC framework.

Many things have changed since I originally wrote that package. Most noticeably, the Web has become the preferred target for delivering services and value to customers. The Web's influence can be said to have changed the landscape of application development and delivery. Cloud based Web services have also contributed to the changing landscape by offering software developers the opportunity to deliver services to their customers without the need to invest in infrastructure and by also providing solutions for wide scalability and resiliency. Numerous cloud options now exist including Amazon's EC2 and Google's App Engine for which I have written numerous applications .

About six months ago one of my customers contacted me about migrating her licenses for Love My Vehicle to new computers her company had purchased. Unfortunately, I wasn't able to offer her any assistance because I had lost the source code to the application a few years back (which could serve as the subject for its own article). As a result I decided to create a modern version of the software targeting, of course, the Web and the cloud and as I already had practical hands on experience with App Engine I opted to target Google's cloud.

One of the early lesson I learned about targeting App Engine is that Google's limit on the amount of time allotted to each HTTP request severely limits what I can and cannot do on their servers. I learned that the best approach was to limit each request to retrieving and updating data only and to do all HTML rendering on the browser using Ajax and DOM manipulation. The added benefit of this approach is the RIA experience for the user.

The applications I already have written for App Engine all use Java and Groovy on the servers for processing Ajax requests and jQuery on the browser for DOM manipulation. The shortcoming to this approach is that client side development tends to be tedious and you lose the benefits provided by compilers and IDEs, especially catching coding errors early and code refactoring. I wondered what other options I had that would offer the same set of resources on the client that I had become accustomed to having on the server side of development. Enter Google's GWT.

GWT is Google's pure Java approach for developing rich internet applications (RIA) and it uses a novel approach of compiling Swing like Java code to native Javascript targeting IE, FF, Chrome and the Safari browsers. Using GWT lets you develop both your servlets and client side code in Java without having to give up your favorite IDE which in my case is Eclipse.

In the course of two months and coding in my spare time I have manged to be very productive using GWT. After studying and learning its "ins and outs" I have already managed to put together a nice little prototype of Love My Vehicle running on Google's App Engine cloud. This isn't a clone of the older application but rather a complete rewrite with new features and of course, Web based. Here's the link: http://lovemyvehicle.appspot.com/. Though early in its life cycle and sans source code for the original product, I am applying my knowledge of the original software's functionality to build out the new product which will support the popular 'freemium' subscription model. 

As I progress in adding and refining functionality I will post updates here. I also intend to write new articles specifically relating to its development that will also include GWT and App Engine.

Screen shots of early prototype








Updated 11/27/2010

Since posting the original article I've made numerous changes to some of the views and I've also implemented a couple of new views, all of which are included below. But first, allow me to make a few obvious but none the less important observations about application development in general.

One of the keys to successful development IMHO is the constant refinement of concepts and ideas. No matter how good a first implementation is there is always room for improvement. As concepts and ideas materialize and as the complexity of the application increases it is very important to review your implementations frequently, looking for ways to improve them. In addition, as development progresses you can sometimes find that you need to reuse an implementation but in its current state it is tightly bound to a single point of use.

IDE refactoring support makes this repetitive cycle of coding and refinement manageable and Eclipse, my preferred choice of IDE, shines in this area saving me literally hours compared to what it would have taken me to manually make all the modifications up to this point.

So, if your current IDE doesn't shine in its refactoring support look to upgrade to a better IDE. JetBrains, Eclipse and Netbeans all provide excellent support for refactoring code and of the 3 only JetBrains requires a paid license for non open source projects.

With that little tidbit out of the way here are the screen shots I promised:

Screen shots of modified views from early prototype





Screen shots of recently added views from early prototype





Updated 12/5/2010

Since my last update I've done a lot more refactoring, made some improvements and changes to the the existing views, implemented the Parts, Fluids and Suppliers views and I've added one new view, Notifications, to the Manage sub menu. The data displayed in the following screen shots is bogus of course and is for testing purposes only, mainly to verify that my sorting routines are working correctly. Screen shots follow:
















Updated 12/19/2010

Complex Web 2.0 pages are highly dynamic and require a lot of DOM manipulation for adding, removing, hiding and showing page elements in response to the user's actions; that's how they mimic desktop applications providing a similar rich user experience.

Love My Vehicle's Misc. Purchases View is one such example of a complex, highly dynamic page that responds to the user's actions by manipulating the DOM accordingly. The view supports the display of a document non editing view of a purchase which has numerous areas on which the user can click on to manipulate such purchase related items as purchase line items and sales tax.

For example, when the user clicks the Add Purchase Item button DOM manipulation is used to display an editor that allows the input of a purchase item. The user can save their input by clicking the editor's Save Purchase Item button or they can cancel the operation by clicking the editor's Cancel button. If they click the Save Purchase Item button the information they entered is first validated and if it is valid the DOM is again manipulated to display a document non editing view of the line item entry. If the information fails validation then the line item editor displays an error message which provides feedback to the user prompting them to correct the data.

The same line item editor also supports editing of an existing purchase line item which would be the case if the user is editing an existing purchase or a line item they previously entered in a new purchase.

Sales tax works similarly to the purchase line item editor supporting both a document non editing view and an editing view.

Whenever the users saves their data in either the line item editor or the sales tax editor the page recalculates the net and gross amounts for the purchase.

In the coming weeks I intend to publish an article dedicated to my approach to developing these types of highly dynamic pages and of course I will focus on using GWT to implement them. It is possible that this will be a multi part article as the topic requires a lot of detail and I think would be easier to consume if it wasn't all tossed out at you at one time.

I have added some screen shots below of the views that I described above as well as a screen shot of the Purchase view which shows a list of all purchases as well as showing a document view of the selected purchase.

I hope you have found this latest update interesting and as always, feel free to provide your feedback.

Have a very happy holiday and new year.






Updated 12/19/2010

In real life one rarely gets the opportunity to do things over but software development is an exception. After implementing the Purchase views I realized that I had failed to provide the user with a report view of a purchase. What do I mean when I say a report view? A report view is any view of data that when viewed looks like a well laid out report and as close to the real life document that it is supposed to represent. An invoice is an example of a report view with a header, line items, and a summary. A purchase is also an example and is very similar to an invoice in that it also has a header, line items and a summary.

Business applications, which Love My Vehicle really is when you get down to it, usually have to provide a lot of report views and implementing them is often time consuming because of the detail required to get the views to look like real documents. I made two passes at implementing the Purchase report view, one using a div only approach and one using tables. In the end I chose the tables approach because it was more straight forward and it allowed me to use GWT's excellent support for table row and cell generation.

The following is a screen shot of a Purchase report view. Besides providing the user with a report view of what a Purchase document should look like, it also provides the user with the ability to edit and delete the backing purchase data:

Friday, March 13, 2009

Netbeans And Apache Wicket

Hi there, Today I will introduce developing Apache Wicket applications using the Netbeans IDE v6.5. So lets get started. Installing Netbeans IDE v6.5 and the Wicket v1.4 Plugin First and foremost, if you haven't already, download and install Netbeans v6.5 which you can find here. By selecting the 'All' bundle option you will download and install everything you need to follow along with the examples. Once you have installed the Netbeans IDE, you should download and install the Wicket plugin for Netbeans v6.5 which you can find here. As there are 2 plugins listed on this page, please make sure that you select, download and install the one for Wicket v1.4 which will install the v1.4 Wicket libraries. Follow the installation instructions as provided on the page. This plugin was contributed by Geertjan Wielenga, a technical writer in the Netbeans Docs team who has contributed an amazing amount of material to the Netbeans community. Creating a Wicket Application With Netbeans and the Wicket plugin installed, now we can create our first Netbeans Wicket project. Start Netbeans and click File | New Project from the main menu. This will open the New Project window as pictured below: In the Categories list select Java Web and in the Project list select Wicket Application and then click Next. Accept all the default options in the Server and Settings window and click Next. In the Framework window, select Wicket 1.4 from the list of available Frameworks and then click Finish as pictured below: This will create a Wicket project which will be opened in the Netbeans IDE as pictured below: The plugin generates numerous files for you including the Server and Web descriptor files which are used to deploy and configure your web application on the application server, as well as basic Java, HTML and resource files that you can use as templates to start developing your application. Select Run | Run Main Project from the main menu to build, deploy and run the application. You should see the following rendered in your client browser: The Structure of a Wicket Application Wicket is different than most other Java Web frameworks that I have worked with or that I am familiar with, in that Wicket's convention is that it expects Java and markup files to reside side-by-side in the same Java package. This can be seen in the above screenshot. A rendered Web page in a Wicket application is implemented with at least 2 files, a Java Class file and a markup file. Both files must have the same names and are case sensitive. As we can see from the above screehshot, both HomePage.java and HomePage.html files are used when there is a request to render the HomePage html file to the client browser and they reside side-by-side to eachother. Just Java and HTML One of the advantages when working with Apache Wicket is that you create your application using just plain old Java, X/HTML, CSS, and resources. Another advantage is that you don't mix markup and scripting in your HTML files as is often the case in other frameworks. In other words, when you view a markup file in a Wicket application you will only see HTML. There is no spaghetti-code intermixed inside your markup. This clean separation of code and markup helps when developing and maintaining your applications by making your applications easier to read and understand. It also allows programmers and designers/graphic artists to work together on the same pages. Designers and graphic artists shouldn't have to be programers in order to do their jobs so not having to work with markup files that have server-side scripting code in them can eliminate that problem. Double click on the HomePage.html file located in the Projects window. It will open in the Netbeans HTLM editor window as pictured below: What you see is what you would expect to see when viewing markup - HTML! Extending Our Application The rendered page in our new application isn't much to look at but it will serve as a foundation to demonstrate adding dynamic content to a web page using Wicket. For this demonstration we will add markup and Java code to render the ubiquitous "Hello, World!" message as well as the current date and time in the client browser. But for the first crack at this, lets cheat and show how to do this by just adding static text to the HomePage.html file. Double click HomePage.html in the Netbeans Project window. The file will open in the Netbeans HTML editor. Add the text as pictured below: Select Run | Run Main Project from the main menu to build, deploy and run the application. You should see the following rendered in your client browser: Adding Dynamic Content If all we want to do is to display static text then our job would be done, but static pages are boring. Lets add some code and markup to make this page display the current date and time as well when the page is rendered. Double click HomePage.html in the Netbeans Project window. The file will open in the Netbeans HTML editor. Modify and add the text as pictured below: Notice that we've added a span tag to the markup and that it has a wicket:id attribute whose value is lblDateTime. When we create a Wicket componet to contribute to the body of this span tag we will pass this same value to the component's constructor as its first parameter which is its id. Double click HomePage.java in the Netbeans Project window. The file will open in the Netbeans Java editor. Modify the HomePage class as pictured below: In the HomePage constructor we obtain and instance of a Calendar object which will be used to get the current date and time. Then we add a Label to the page. A Label is a Wicket component that adds its content to the body of any HTML element that it is associated with. The association between the HTML element and the component is made through the component's id value which we pass as the first parameter in the Label's constructor. The id value we pass is the same value that was assigned to the wicket:id attribute of the span tag in the HomePage.html file. The second parameter we pass in the Label's constructor is the value of what we want to add to the body of the span element that the Label component is associated with. In this case, we will pass the current date and time as a string. Select Run | Run Main Project from the main menu to build, deploy and run the application. You should see the following rendered in your client browser: Although this application is trivial, the principles used here are the same ones used when developing real world enterprise Wicket applications. Synergy - Netbeans and Wicket As demonstrated, Netbeans with the Wicket v1.4 plugin provide many features and services for creating, developing and maintaining your Wicket applications. It is a highly productive and intuitive environment. Wicket offers Java Web developers a simple, intuitive, and productive framework to create Web applications with. Now that Netbeans has solid support for Wicket, I believe both will continue to grow in popularity.

About Me

My photo
New York, NY, United States
Software Developer