1 Reply Latest reply on Aug 21, 2014 11:26 AM by fagnerffcs

    Custom @Converter for a class with @EmbeddedId

    rodrigo.bento

      Hello,


      I'm having trouble definig a converter for a class with embedded id.


      It's simple to return an object and a string of the id for entities with single ids,
      but I don't know how to implement a custom converter for a class with composite id and return properly as object and as string.


      I've been searching a lot for examples but I couldn't find.


      What I want to do is to ser this custom converter for a class with a composite id in order to properly setup a h:selectItem.


      I'm using Seam 2.1.2GA with Tomcat 6.0.18 and MySQL 5.x.


      Everything is working fine, I'm just stuck at this converter issue.


      Anyone has an example or could give me some clue?


      Follow some relevant code:


      // The Service class which has an @EmbeddedId
      
      @Entity
      @Name("service") 
      @Table(name="scf_service")
      public class Service implements Serializable {
      
           private static final long serialVersionUID = 6496138369915841462L;
      
           private ServicePk pk = new ServicePk();
      
           public Service() {
           }
           
           @EmbeddedId
           public ServicePk getPk() {
                return this.pk;
           }
           
           @Transient
           public Product getProduct() {
                return this.pk.getProduct();
           }     
      
           @Transient
           public User getUser() {
                return this.pk.getUser();
           }
      
           public void setPk(ServicePk pk) {
                this.pk = pk;
           }     
           
           @Transient
           public void setProduct(Product product) {
                this.pk.setProduct(product);
           }     
           
           @Transient
           public void setUser(User user) {
                this.pk.setUser(user);
           }     
           ...
      }



      // The EmbeddedId class
      
      public class ServicePk implements Serializable {
      
           private static final long serialVersionUID = 7943185356676494310L;
      
           private Product product;     
           private User user;
           
           public ServicePk() {
           }
           
          @ManyToOne
          @JoinColumn(name="product_id", nullable=false)
           @ForeignKey(name="fk_service_product")
           public Product getProduct() {
                return product;
           }
           
           @ManyToOne
           @JoinColumn(name="user_id", nullable=false)
           @ForeignKey(name="fk_service_user")     
           public User getUser() {
                return user;
           }
      
           public void setProduct(Product product) {
                this.product = product;
           }
           
           public void setUser(User user) {
                this.user = user;
           }     
           ...
      }



      // The converter
      
      @Name("serviceConverter")
      @org.jboss.seam.annotations.faces.Converter(forClass=Service.class)
      @BypassInterceptors
      public class ServiceConverter implements Converter, Serializable {
      
           private static final long serialVersionUID = -1115108812204913185L;
           
           @Logger 
           private Log log;
      
           public Object getAsObject(FacesContext context, UIComponent component, String value) {
                
                log.debug("converting service as object...");
                
                log.debug("value: " + value);
                
                // I don't know how to properly retrieve the Service since I get a String as a value, and my primary key is a ServicePk (EmbeddedId)
                
                log.debug("result is null");
                
                return null;
           }
      
           public String getAsString(FacesContext context, UIComponent component, Object value) {
                
                log.debug("converting service as string...");
                
                if (value instanceof Service) {
                     
                     Service service = (Service) value;
                     
                     return String.valueOf("i don't know the proper way to return the composite id as string");               
                } 
                
                log.debug("result is null");
                     
                return null;
           }
      }



      Any help would be appreciated.


      Thanks,


      Rodrigo

        • 1. Re: Custom @Converter for a class with @EmbeddedId
          fagnerffcs

          Rodrigo,

           

          I know it's been a while since you asked this question, but I had a similar problem and one possible solution is this way:

           

          Define ServicePk toString method in order to recover properly;

           

          @Override
          public String toString() {
            return this.user.getId() + ";" + this.product.getId();
          }
          
          
          

           

          Next step is to change your converter in order to get these values

           

           

          @PersistenceContext
          private EntityManager em;
          
          @Override
          public Object getAsObject(FacesContext context, UIComponent component, String value) {
                    log.debug("converting service as object...");  
                    log.debug("value: " + value);  //it'll print toString method
                    String[] vals = value.split(";");
                    Service service = (Service) em.createQuery("SELECT s FROM Service s WHERE s.pk.user.id = :user AND s.pk.product.id = :product)
                                                .setParameter("user", Integer.parseInt(vals[0]))
                                                .setParameter("product", Integer.parseInt(vals[1]))
                                                .getSingleResult();
                    log.debug(service.toString()); //print service info
          
                    return service;
          
          }
          
          @Override
          public String getAsString(FacesContext context, UIComponent component, Object value) {
               return String.valueOf(((Service) value).getPk());
          }
          
          
          
          
          

          I hope this could be some use for you or another one with a similar problem.