2013/10/02

Generic entity converter in JSF 2 and EE 6

In this post I would like to show you how you can create universal entity converter for most of your entities. Steps to do:

  1. Create EntityConverter class which implements javax.faces.convert.Converter interface
  2. Override getAsObject() and getAsString() methods
How this converter works:
  • If you need to convert entity to String, converter will create it from class canonical name and from value of id field. This field is annotated by @Id in your entity class. 
  • In case of other direction (convert to Object), it will split created string to class name and id value and try to load object from persistence storage.
Here is example of this converter:



import java.lang.reflect.Field;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.Id;

@Named
public class EntityConverter implements Converter {

 @Inject
 private EntityManager em;

 public Object getAsObject(FacesContext fc, UIComponent component, String string) {
  try {
   String[] split = string.split(":");
   return em.find(Class.forName(split[0]), Long.valueOf(split[1]));
  } catch (NumberFormatException | ClassNotFoundException e) {
   return null;
  }
 }

 public String getAsString(FacesContext fc, UIComponent component, Object object) {
  try {
   Class<? extends Object> clazz = object.getClass();
   for (Field f : clazz.getDeclaredFields()) {
    if (f.isAnnotationPresent(Id.class)) {
     f.setAccessible(true);
     Long id = (Long) f.get(object);
     return clazz.getCanonicalName() + ":" + id.toString();
    }
   }
  } catch (IllegalArgumentException | IllegalAccessException e) {
  }
  return null;
 }
}
And how to uset it? Not so big issue. In this example we want to show all user roles and user can choose from them:
<h:selectmanycheckbox converter="#{entityConverter}" value="#{bean.roles}">
  <f:selectitems itemlabel="#{role.rolename]}" itemvalue="#{role}" 
    value="#{bean.allRoles}" var="role">
  </f:selectitems>
</h:selectmanycheckbox>
If you have different Id types in different classes you can use converter like this. It will call valueOf method on your Id field type class. For example you have field userId which is Integer type, it will call Integer.valueOf(valueFromPage). This way you can load entity from entityManager because you have type of your entity and id of this entity with correct type.

@Named
public class EntityConverter implements Converter {

 @Inject
 private EntityManager em;

 @Inject
 Logger log;

 public Object getAsObject(FacesContext fc, UIComponent component,
   String string) {
  try {
   String[] split = string.split(":");
   Class clazz = Class.forName(split[0]);
   for (Field f : clazz.getDeclaredFields()) {
    if (f.isAnnotationPresent(Id.class)) {
     Method valueOfMethod = f.getType().getMethod("valueOf",
       String.class);
     return em.find(clazz, valueOfMethod.invoke(null, split[1]));
    }
   }
  } catch (ClassNotFoundException | NoSuchMethodException
    | SecurityException | IllegalAccessException
    | IllegalArgumentException | InvocationTargetException e) {
   log.warn("Cannot convert", e);
  }
  return null;
 }

 public String getAsString(FacesContext fc, UIComponent component,
   Object object) {
  try {
   Class clazz = object.getClass();
   for (Field f : clazz.getDeclaredFields()) {
    if (f.isAnnotationPresent(Id.class)) {
     f.setAccessible(true);
     return clazz.getCanonicalName() + ":" + f.get(object);
    }
   }
  } catch (IllegalArgumentException | IllegalAccessException e) {
   log.warn("Cannot convert", e);
  }
  return null;
 }
▼ Click here to say thanks ▼

2013/09/17

Https SoapUI mock service standalone

This post will try to show you how you can create secure SOAP service. We need to have few things before start:

  1. SoapUI - Download
  2. Your certificate - How to create it
  3. WSDL - Simple WSDL example
Start your SoapUI and create new soapUI project lik this:


Click OK to all questions. Your workspace now contains 'test-project' soapUI project under which you can find 'exampleSOAP' interface and 'exampleSOAP MockService'.


Start mock service by righ-click on 'exampleSOAP MockService' and select 'Start minimized'. If you have clean workspace without any changes in Preferences in SoapUI, mock service should listen on:

 http://COMPUTER_NAME:8088/mockexampleSOAP

You can also open WSDL file in you browser by following URL:

 http://COMPUTER_NAME:8088/mockexampleSOAP?WSDL

Next we can test your mock service by some request. Open 'Request1' under 'exampleSOAP/NewOperation':


You can see message '-no endpoint set-' or something like 'http://www.example.org/' in list box above request body. We need to add URL of our mock service to this list. Right-click on 'exampleSOAP MockService' and select 'Add Endpoint to Interface'.


Select new URL of our mock service in list box in request1 window.


Here is output:


We have running mock service and we can test it by SoapUI now. Save our project and open Preferences (Ctrl+Alt+P). Here we need to configure SSL for our mock service:


SSL port is different from port of your mock service (SSL = 18088, Service = 8088). Save preferences (File > Save preferences) and restart whole SoapUI. It has some issue with loading of certificates if you do not restart.

Start mock service againt.

Change endpoint protocol from https to http in URL and port from 8088 to 18088. Test you mock service. Is it working?

If you need to start you mock service without GUI, you can do it. Go to bin directory and try follow command:

mockservicerunner.bat -m "exampleSOAP MockService" test-project-soapui-project.xml

Argument -m contains name of the MockService and xml file is your project file. More info about arguments can find here.
▼ Click here to say thanks ▼