Another Custom Wicket Component - DateDropDownField


I needed a date drop down component (see below) for my current project. Unfortunately, I couldn't find a built-in Wicket component that does the job. So why not write my own???




Java Code

  1. public class DateDropDownField extends FormComponentPanel<Date>
  2. {
  3.   private static final long serialVersionUID = -839727513016106766L;
  4.  
  5.   private int month, day, year;
  6.   private final DropDownChoice<Integer> monthField;
  7.   private final DropDownChoice<Integer> dayField;
  8.   private final DropDownChoice<Integer> yearField;
  9.  
  10.   public DateDropDownField(String id, IModel<Date> model)
  11.   {
  12.     super(id, model);
  13.  
  14.     // create month field
  15.     monthField = new DropDownChoice<Integer>("month",                                    
  16.                    new PropertyModel<Integer>(this, "month"), // bind model
  17.                    getMonths(),                               // list of choices
  18.                    new MonthRenderer());                      // renderer
  19.     monthField.setLabel(new Model<String>("month"));
  20.     monthField.add(new RangeValidator<Integer>(0, 11));       // add a simple validator
  21.    
  22.     // create day field
  23.     dayField = new DropDownChoice<Integer>("day",
  24.                    new PropertyModel<Integer>(this, "day"), getDays());
  25.     dayField.setLabel(new Model<String>("day"));
  26.    
  27.     // create year field
  28.     yearField = new DropDownChoice<Integer>("year",
  29.                    new PropertyModel<Integer>(this, "year"), getYears());
  30.     yearField.setLabel(new Model<String>("year"));
  31.    
  32.     add(monthField);
  33.     add(dayField);
  34.     add(yearField);
  35.   }
  36.  
  37.   @Override
  38.   public void onBeforeRender()
  39.   {
  40.     // initialize model
  41.     Date date = getModelObject();
  42.     if(date == null)
  43.     {
  44.       date = new Date();
  45.       setModelObject(date);
  46.     }
  47.    
  48.     // synchronize main model and drop down components
  49.     Calendar cal = Calendar.getInstance();
  50.     cal.setTime(date);
  51.     month = cal.get(Calendar.MONTH);
  52.     day = cal.get(Calendar.DAY_OF_MONTH);
  53.     year = cal.get(Calendar.YEAR);
  54.    
  55.     super.onBeforeRender();
  56.   }
  57.  
  58.   @Override
  59.   public void convertInput()
  60.   {
  61.     try
  62.     {
  63.       // get values from individual components
  64.       int month = monthField.getConvertedInput();
  65.       int day = dayField.getConvertedInput();
  66.       int year = yearField.getConvertedInput();
  67.      
  68.       // TODO check for valid date (example - 02/31/11 is invalid)
  69.      
  70.       // update the model from converted input
  71.       Calendar calendar = Calendar.getInstance();
  72.       calendar.set(Calendar.MONTH, month);
  73.       calendar.set(Calendar.DAY_OF_MONTH, day);
  74.       calendar.set(Calendar.YEAR, year);
  75.       setConvertedInput(calendar.getTime());
  76.     }
  77.     catch(Exception e){
  78.       setConvertedInput(null);
  79.     }
  80.   }
  81.  
  82.   // month choices
  83.   private List<Integer> getMonths() {...}
  84.  
  85.   // day choices
  86.   private List<Integer> getDays() {...}
  87.  
  88.   // year choices
  89.   private List<Integer> getYears() {...}
  90.    
  91.   // render months as names instead of numbers
  92.   private class MonthRenderer extends ChoiceRenderer<Integer>{
  93.     private static final long serialVersionUID = -9037815586384085976L;
  94.     @Override
  95.     public String getDisplayValue(Integer object)
  96.     {
  97.       SimpleDateFormat format = new SimpleDateFormat("MMM");
  98.             Calendar cal = Calendar.getInstance();
  99.             cal.set(Calendar.MONTH, object);
  100.             return format.format(cal.getTime());
  101.     }
  102.   }
  103. }

HTML Code

  1. <html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
  2.   <body>
  3.     <wicket:panel>
  4.       <select wicket:id="month"></select>
  5.       <select wicket:id="day"></select>
  6.       <select wicket:id="year"></select>
  7.     </wicket:panel>
  8.   </body>
  9. </html>


Again, Wicket saved the day. Here's another reusable and self-contained component. To use this anywhere in your code, you simply need to add this new component to a form, panel, etc. No need to duplicate code or html markup!


Java Code

  1. add(new DateDropDownField("date", new Model<Date>(new Date())));








Extending Wicket's AjaxFallbackDefaultDataTable


I was looking for a Wicket datatable component with sorting, paging and ajax support. Fortunately, I found this component.The only problem is, I want to be able to apply a different background style when selecting each row (hover) and execute some action when the entire row is clicked. These features are not supported out-of-the-box.




Luckily, Wicket makes it very easy to extend components. All I had to do was hook into the method that creates each row object and add the new behavior. Here's the code...


Java Code

  1. public class CustomAjaxFallbackDefaultDataTable<T> extends AjaxFallbackDefaultDataTable<T>
  2. {
  3.    // Constructor
  4.    public CustomAjaxFallbackDefaultDataTable(String id,
  5.                                              List<IColumn<T>> columns,
  6.                                              ISortableDataProvider<T> dataProvider,
  7.                                              int rowsPerPage)
  8.    {
  9.       super(id, columns, dataProvider, rowsPerPage);
  10.    }  
  11.  
  12.    @Override
  13.    protected Item<T> newRowItem(String id, int index, final IModel<T> model)
  14.    {
  15.       // let super class create row item as usual
  16.       final Item<T> item = super.newRowItem(id, index, model);
  17.      
  18.       // add style on mouse over
  19.       item.add(new SimpleAttributeModifier("onmouseover",
  20.                                            "this.style.backgroundColor='#80b6ed';"));
  21.              
  22.       // remove style on mouse out                                    
  23.       item.add(new SimpleAttributeModifier("onmouseout",
  24.                                            "this.style.backgroundColor='';"));
  25.      
  26.       // execute when row is clicked
  27.       item.add(new AjaxEventBehavior("onclick"){
  28.          protected void onEvent(AjaxRequestTarget target){
  29.             executeOnClick(target, item.getModel());
  30.          }
  31.       });
  32.      
  33.       return item;
  34.    }
  35.    
  36.    public void executeOnClick(final AjaxRequestTarget target, final IModel<T> rowItem)
  37.    {
  38.       String message = rowItem.getObject() + " was clicked";
  39.        
  40.       // execute server side code
  41.       System.out.println(message);
  42.        
  43.       // execute client side code
  44.       target.appendJavascript("alert('" + message + "');");
  45.    }
  46. }


Now the table looks something like this...



As you can see, I was able to extend a component with minimal effort. In addition, this component is reusable. The user can simply override the executeOnClick method if a different action is required when the row is clicked. Try that with JSF =)












Drupal / Java Integration


Drupal is one of the best open source content management systems currently available. One of Drupal's strengths is its module development architecture. It allows developers to extend Drupal's core features in a non-invasive and elegant manner. My only problem with Drupal is that it is written in .... PHP.


I am not a PHP expert, but I am an experienced Java Developer. I have written and deployed many Java enterprise applications in production. I am very familiar with a number of Java frameworks and technologies such as Spring, Struts, JSF, Wicket, JPA, JMS, Web Services, etc. I am also proficient on several Java development/testing tools. However, I do not know of any Java open source projects that can provide all of Drupal's features out-of-the-box.


Luckily, I found a way to integrate Drupal/PHP and Java using the Quercus PHP engine. Because Quercus can run PHP scripts and expose Java methods in PHP, I was able to write Drupal modules by calling Java methods inside PHP functions. I can write most of the business logic in Java and only use PHP to write the Drupal "hooks"!.


I was also able to integrate other Java frameworks such as Spring, Vaadin and Wicket. I used SiteMesh to decorate the Wicket/Vaadin pages using the same Drupal theme.


Check out my POC web application here!








Syndicate content (C01 _th3me_)