vrijdag 8 november 2013

Hello World with Wicket, Maven and embeddable Jetty in Eclipse - Part 2: Adding components

To add a component there are two things that we need to create:
  1. html file
  2. java class file

In Wicket the convention is to add html files to the same package as the class file is, this isn't mandatory.

1. html file
The html file tells wicket where to put which component.

2. java class file
Tells Wicket to fill the elements with which components and/or data.

In part 1 I've set up a basic application, in which I've added a HTML file and a Java class file. For this example I'm going to reuse these files and add a tabpanel there.

I've updated the HTML file by adding a placeholder for the tabpanel. HelloWicket.html now looks like:

<!DOCTYPE html>
<html>
<body>

 <h1 wicket:id="message">Message goes here</h1>

 <div wicket:id="tabs" class="tabpanel" />

</body>
</html>

I've added the next few lines to HelloWicket.java and created the method addTabs(), which returns an empty List for now.
List<AbstractTab> tabs = addTabs();
add(new TabbedPanel<AbstractTab>("tabs", tabs));

Adding tabs

A tab panel without tabs isn't very useful... so lets start with adding tabs to the tab panel.

I've created four tab panels named: TabPanel1 through 4 (not very creative, I know).

Here's the HTML from TabPanel1.html
<wicket:panel>
 <h1>Tab 1 - TextField Example</h1>
</wicket:panel>

Notice that for the Panel a Wicket specific tag is used.

And the corresponding Java from TabPanel1.java

public class TabPanel1 extends Panel {

 public TabPanel1(String id) {
  super(id);
 }

}

TabPanel1 extends Panel. This matches to the html tag <wicket:panel>.

At this point a tab is created, but it isn't added to the tab panel yet.

Add tab to tab panel

To add the tab to the tab panel, we first need to know where to add it. In the HelloWicket.html the tab panel is added (see example above). The tabs are added in HelloWicket.java through the following Java code:
private List<AbstractTab> createTabs() {
 List<AbstractTab> tabs = new ArrayList<AbstractTab>();

 AbstractTab tab1 = new AbstractTab(new Model<String>("first tab")) {
  public Panel getPanel(String panelId) {
   return new TabPanel1(panelId);
  }
 };

 tabs.add(tab1);

 return tabs;
}

The tab is now added to the tab panel. When you run the application you'll see a tab containing a Header with Tab 1.

Check out the sources to see the complete application with all four tabs all containing other components


References:

Source code (GitHub)

Wicket component reference (including link to source code)

Wicket user guide (free ebook)


dinsdag 5 november 2013

Hello World with Wicket, Maven and embeddable Jetty in Eclipse - Part 1: Setting up project

Currently I'm starting to get to know Wicket for a project at work. For this, I've set up a hello world application. I've created a step-by-step description on how to create a basic application.

1. Create Dynamic web project in Eclipse.

2. Convert to Maven project
    a. Add necessary folders (if not added automatically):

src/main/java
src/main/resources
src/main/server
src/test/java
src/test/resources

    b. Add configuration for the folders in pom.xml:
<resources>

 <resource>
  <filtering>false</filtering>
  <directory>src/main/resources</directory>
 </resource>

 <resource>
  <filtering>false</filtering>
  <directory>src/main/java</directory>
  <includes>
   <include>**/*.java</include>
  </includes>
 </resource>

 <resource>
  <filtering>false</filtering>
  <directory>src/main/server</directory>
 </resource>

</resources>

<testResources>

 <testResource>
  <filtering>false</filtering>
  <directory>src/test/resources</directory>
 </testResource>

 <testResource>
  <filtering>false</filtering>
  <directory>src/test/java</directory>
  <includes>
   <include>**/*.java</include>
  </includes>
 </testResource>

</testResources>

<sourceDirectory>src/main/java</sourceDirectory>


3. Add Wicket dependency to pom
<dependency>
        <groupId>org.apache.wicket</groupId>
        <artifactId>wicket-core</artifactId>
        <version>${wicket.version}</version>
</dependency>


4. Add Jetty dependencies to pom
<dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-server</artifactId>
        <version>${jetty.version}</version>
        <scope>provided</scope>
</dependency>

<dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-webapp</artifactId>
        <version>${jetty.version}</version>
        <scope>provided</scope>
</dependency>


5. Add Java Servlet API dependency
<dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>${javax.version}</version>
        <scope>provided</scope>
</dependency>


6. Create Application class
The application class should extend WebApplication and implement the getHomePage() method. In the getHomePage() method the HomePage class should be returned (e.g. HelloWicket.class).

package nl.sparkle.hellowicket;

import org.apache.wicket.Page;
import org.apache.wicket.protocol.http.WebApplication;

public class HelloWicketExample extends WebApplication {

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

}


7. Create WebPage class
The WebPage class should extend WebClass.

package nl.sparkle.hellowicket;

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

public class HelloWicket extends WebPage {
        private static final long serialVersionUID = -1099836337542784152L;

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


8. Create html file
By default this HTML file must have the same name of the related page class and must be in the same package (maybe it's possible to create the same structure in the resources folder and add the HTML files there, but haven't looked at it at time of writing).

<!DOCTYPE html>
<html>
<body>
    <span wicket:id="message">Message goes here</span>
</body>
</html> 


9. Create web.xml in src/main/server/webapp/WEB-INF/

<web-app version="3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <display-name>Wicket Examples</display-name>

    <filter>
        <filter-name>HelloWicketExample</filter-name>
        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
        <init-param>
          <param-name>applicationClassName</param-name>
          <param-value>nl.sparkle.hellowicket.HelloWicketExample</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>HelloWicketExample</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>


10. Start server

package nl.sparkle.hellowicket;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.bio.SocketConnector;
import org.eclipse.jetty.webapp.WebAppContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Start {
        private static final Logger LOGGER = LoggerFactory.getLogger(Start.class);

        /**
         * Startup method.
         *
         * @param args
         * the arguments (none?)
         * @throws Exception
         * any exception.
         */
        public static void main(String args[]) throws Exception {
                new Start().start();
        }

        /**
         * Starts the server.
         *
         * @throws Exception
         * when bad things happen.
         */
        public void start() throws Exception {
                String hostname = "localhost";
                int port = 8080;
                String webappPath = Start.class.getClassLoader().getResource("webapp")
                                .getFile();

                Server server = new Server();

                WebAppContext webapp = new WebAppContext();
                webapp.setContextPath("/");
                webapp.setResourceBase(webappPath);
                webapp.setParentLoaderPriority(true);

                server.setHandler(webapp);

                // socket connector supposedly solves problem with windows lock on files
                SocketConnector connector = new SocketConnector();
                connector.setPort(port);
                connector.setHost(hostname);
                server.addConnector(connector);

                server.start();

                String hostedAddress = "http://" + hostname + ":" + port + "/";
                LOGGER.info("Started web application on: {}", hostedAddress);
                server.join();
        }

}


Application is now accessible through http://localhost:8080/

The source can be found on GitHub: https://github.com/sparkle-sparkle/HelloWicketExample

A Wicket project can also be created using Maven from the command-line see the Quickstart on how to do so.

vrijdag 1 november 2013

Oracle Certified Professional Java Programmer

After some time of preparation I decided, at the end of september, that it was time to pick a date. I decided that all of the preparation that I still needed to do, could be done within a month.

Last wednesday was my exam day. I went to the testing facility (which was easy to find, thanks to a colleague who told me the door was easy to miss). Once I've gotten there I had to register... it took some time before they found my name... because I'm a woman they assumed I wouldn't be there for a technical exam (they offer a lot of different exams). Yay for prejudices.

After registration was complete it was time to take the test.
While I was preparing for the test, in the book that I used, they focused a lot about small things that could cause compiler errors (e.g. missing semi-colons (;)). In the actual exam there were questions that were tricky, but less than I had anticipated.
After I finished the test, I went back to the registration desk to get my things. Right after I turned my phone back on, I received an email from Oracle stating I could see my test results online (at the end of the test there's a message on the computer stating that you'd have to wait 30 minutes before you can see your result). I passed my exam and when I notified my colleagues, they wanted to know where the cake was ;-)