Monday, December 18, 2017

Problems with Primefaces Picklists

Primefaces is awesome. JSF is awesome.

Know what isn't awesome? The documentation.

Don't get me wrong... The Primefaces document and the Showcase demo site are very good for introducing the components and the basics on how to use them. The problem is that sometimes they're a little too basic. For example, the picklist component. It says right in the Primefaces PDF that most often, pojos will be used with the picklist, and that it is necessary to implement a Converter to handle it... and that's it. It goes on to show how some facets can be used to make the component look more spiffy, but the developer is left with very little information on what the Converter is for, exactly and how to implement it.

That's why this post exists.

So here's an example that will hopefully help.

<p:picklist converter="#{shipConverter}" itemlabel="#{ship.name}" value="#{backingBean.pickDLM}" var="ship"/>

So here, the converter is just the name we give to our instance of the ShipConverter class, which implements Converter.  itemLabel is the field within one of the contained objects that will be displayed in the picklist windows.  Value is the DualListModel which is defined in the backing bean and serves as the source of data for the picklist.  Var is the reference to each individual item, the same as in a table or tree.

So how does that DualListModel work?

In your backing bean, you'll need your data source for the picklist. 

DualListModel<Ship> pickDLM = null;  //matches the value field on the view
List<Ship> shipSource = DatabaseSourceObject.getShips();
List<Ship> shipTarget = newArrayList<Ship>();

Notice that the source object is a list of Ship objects which will populate the left pane of the picklist.  The target is the right pane, and is initially empty.  If your project needed to pre-populate a few items in the right pane, you would add them to the target object here.  So now we put it all together:

pickDLM = new DualListModel<Ship(shipSource, shipTarget);

So then all you need in your backing bean is the getters and setters for the DualListModel. 

Now for the Converter...

@FacesConverter(value="shipConverter")
@Managedbean(name="shipConverter")
public class ShipConverter implements Converter{

  public ShipConverter(){}//Constructor Stub
  
  //This method provides an implementation for converting the strings in the pickList view back into the objects they represent.
  @Override
  public Object getAsObject(FacesContext context, UIComponent uiComponent, String value){
  pickList pickList = (PickList)uiComponent;
  DualListModel listModel = (DualListModel)pickList.getValue();
  for(Object item : listModel.getSource()){
    Ship ship = (Ship)item;
    if(ship.getName().equals(value)){
      return ship;
    }
  }
}

  //This method provides an implementation for getting the String value of an object in the picklist.
@Override
public String getAsString(FacesContext context, UIComponent uiComponent, Object object){
  String result = ((Ship)object).getName();
  return result;
}
}

That's it.  The idea is to specify exactly how to switch back and forth between the collection objects and their String representations in the picklist.

Enjoy!


Tuesday, April 11, 2017

CentOS 7 Networking in VirtualBox

I see a lot of results when Google searching on this problem and there is a wide variety of solutions, so this one may or may not work for you. It's a hybrid of a couple others I saw, and was arrived at through trial and error.

The environment:

Windows 7 (Host OS, and no I don't have Admin rights) CentOS 7 (Guest, I have root privileges) Oracle VM VirtualBox 4.3

Installing CentOS 7 into VirtualBox requires that you explicitly tell the VM that the ethernet cable is plugged in. That's no big deal in and of itself, but there's some configuration to be done.

Open the file /etc/sysconfig/network/scripts/ifcfg-enp0s3

Note that the filename is based on the name of your ethernet connection. If you don't know what that is, run an ifconfig command to find out.

Modify the following two lines in the file:

BOOTPROTO=shared change to BOOTPROTO=dhcp

ONBOOT=no change to ONBOOT=yes

Reboot your CentOS and verify. That's the approach that worked for me.

Monday, March 6, 2017

Liferay 7 Portlet pom.xml Issues in Eclipse

So I'm learning my way around Liferay 7 and one of my first efforts was to create a sample portlet for it.  The issue I was experiencing was that two of the dependencies were not able to resolve:

        <dependency>
            <groupid>com.liferay.portal</groupid>
            <artifactid>portal-service</artifactid>
            <version>${liferay.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupid>com.liferay.portal</groupid>
            <artifactid>util-java</artifactid>
            <version>${liferay.version}</version>
            <scope>provided</scope>
        </dependency>

The problem is that these dependencies, being auto generated by the Eclipse Liferay plugin, are using the older Liferay 6 naming conventions.  The newer naming conventions look like this:

        <dependency>
            <groupid>com.liferay.portal</groupid>
            <artifactid>com.liferay.portal.kernel</artifactid>
            <version>2.22.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupid>com.liferay.portal</groupid>
            <artifactid>com.liferay.util.java</artifactid>
            <version>2.2.2</version>
            <scope>provided</scope>
        </dependency>

Note, the artifactId now has a '.' delimited format instead of '-,'  and the version isn't the same as the Liferay version.  A complete list of the new names appears here.