Hi Folks,

since my last post i elaborated a workaround for the issue:
proving additional getters and setters only for OCM and
move the annotations to the getters.
This works, buts its not what i would call clean code!

Here a code example:

@Node(jcrType="my:imageimpl", extend=MyBagImpl.class, discriminator=false)
@Implement(interfaceName=IMyImage.class)
public class MyImageImpl extends MyBagImpl implements IMyImage {
 protected IMyResource image;

 public IMyResource getImage() {
     return image;
 }

 public void setImage(IMyResource image) {
     this.image = image;
 }

@Bean(jcrName="my:image", proxy=true, converter=DefaultBeanConverterImpl.class)
 public MyResourceImpl getImageOCM() {
     return (MyResourceImpl)image;
 }

 public void setImageOCM(MyResourceImpl image) {
     this.image = (MyResourceImpl)image;
 }

 //...
}


Interfaces are same as before and usage in my domain is only over the interfaces.


Is there a neat solution under way?


Thanks in advance,
Kadir






Kadir Alaca schrieb:
Hi Christophe,

thanks for reply.

Here some additional code with regards,
Kadir


public interface IJcrNodeDAO<T, I extends Serializable> {
   T insert(final T object);
   T find(final String path);
   T update(final T object);
   //...
}


public class JcrNodeDAOImpl<T extends IMyBag, I extends Serializable>
       implements IJcrNodeDAO<T, I> {
   @Autowired
   @Qualifier("jcrMappingTemplate")
   protected transient JcrMappingTemplate jcrTemplate;

   public T insert(final T object) {
       return (T)jcrTemplate.execute(new JcrMappingCallback() {
           public Object doInJcrMapping(ObjectContentManager manager)
                   throws JcrMappingException {
               manager.insert(object);
               manager.save();
               return object;
           }
       });
   }

   public T find(final String path) {
       return (T)jcrTemplate.execute(new JcrMappingCallback() {
           public Object doInJcrMapping(ObjectContentManager manager)
                   throws JcrMappingException {
               return manager.getObject(path);
           }
       });
   }

   public T update(final T content) {
           return (T) jcrTemplate.execute(new JcrMappingCallback() {
               public Object doInJcrMapping(ObjectContentManager manager)
                       throws JcrMappingException {
                   try {
                       manager.checkout(content.getPath());
                       manager.update(content);
                       manager.save();
                       manager.checkin(content.getPath());
                   } catch (VersionException ex) {
                       throw new JcrMappingException(ex);
                   }
                   return content;
               }
           });
   }
   //...
}


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:web/WEB-INF/config/spring/applicationContext4tests_jcr.xml"})
@Transactional
public class JcrEventHandlerTest {
   @Autowired(required=true)
   @Qualifier("jcrNodeDaoBag")
   protected IJcrNodeDAO<IMyBag, UUID> nodeDaoBag;

   @Autowired(required=true)
   @Qualifier("jcrNodeDaoImage")
   protected IJcrNodeDAO<IMyImage, UUID> nodeDaoImage;
     private String path = "/Kibo_1";

   //...
     @Test
   private void test_Insert_Image_Type1() {
IMyImage image1 = create_a_image_through_some_weird_factory(...);
           image1.setPath( path );
           nodeDaoImage.insert(image1);
   }

   @Test
   private void test_Update_Image_Type1() {
       String new_label = "New Label";

       IMyImage img = nodeDaoImage.find(path);
       img.setLabel(new_label);

       nodeDaoImage.update(img);

       IMyImage img2u = nodeDaoImage.find(path);

       assertEquals(new_label, img2u.getLabel());
   }
   //...
}





Christophe Lombart schrieb:
Hi Kadir,

Do you have a small unit test. If you have one, it will be easier to
review your classes.
I would like to review it maybe it is a bug in the OCM code.

Thanks,
Christophe


2009/9/13 Kadir Alaca <[email protected]>:
Hi,

i have an interface IMyImage and its implementation in MyImageImpl.
MyImageImpl has @Bean-Fields which refer to the interface IMyResource.
IMyResource is implemented in MyResourceImpl.

But here the related code:


@Node(isInterface=true, jcrType="my:bag", discriminator=false)
public interface IMyBag {
  //getter and setter defs for path, uuid and other
}

@Node(isInterface=true, jcrType="my:image", extend=IMyBag.class,
discriminator=false)
public interface IMyImage extends IMyBag {
  IMyResource getImage();
  void setImage(IMyResource resource);
  //...
}

@Node(isInterface=true, jcrType="my:resource", discriminator=false)
public interface IMyResource {
  InputStream getData();
  void setData(InputStream data);
  //...
}

@Node(jcrType="my:bagimpl", isAbstract=false, discriminator=false)
@Implement(interfaceName=IMyBag.class)
public class MyBagImpl implements IMyBag {
  @Field(path = true)
  private String path;

  @Field(uuid=true)
  private String UUID;
  //...
}

@Node(jcrType="my:imageimpl", extend=MyBagImpl.class, discriminator=false)
@Implement(interfaceName=IMyImage.class)
public class MyImageImpl extends MyBagImpl implements IMyImage {
  @Bean(jcrName="my:image", proxy=true,
converter=DefaultBeanConverterImpl.class)
  protected IMyResource image;

  public IMyResource getImage() {
      return image;
  }

  public void setImage(IMyResource image) {
      this.image = image;
  }
  //...
}

@Node(jcrType="my:resourceimpl", isAbstract=false, discriminator=false)
@Implement(interfaceName=IMyResource.class)
public class MyResourceImpl implements IMyResource {

  @Field(jcrName="my:binarydata")
  protected byte[] binarydata;

  public byte[] getBinarydata() {
      return binarydata;
  }

  public void setBinarydata(byte[] binarystream) {
      this.binarydata = binarystream;
  }

  public InputStream getData() {
      return new ByteArrayInputStream(this.binarydata);
  }

  public void setData(InputStream data) {
          this.binarydata = FileUtils.toByteArray(data);
  }
  //...
}





When i insert such an image, OCM works pretty fine.
Applying an update on that inserted image results to the following
exception:

Repository access exception; nested exception is
org.apache.jackrabbit.ocm.exception.IncorrectPersistentClassException: Class
of type: java.lang.Object has no descriptor.
org.springmodules.jcr.JcrSystemException: Repository access exception;
nested exception is
org.apache.jackrabbit.ocm.exception.IncorrectPersistentClassException: Class
of type: java.lang.Object has no descriptor.

I have debugged OCM and found that

  public static Class getBeanClass(Object bean)
  {
       Class beanClass = bean.getClass();
       if (isProxy(beanClass))
       {
               //CGLIB specific
               return beanClass.getSuperclass();
       }
       return beanClass;
  }

in org.apache.jackrabbit.ocm.reflection.ReflectionUtils returns
java.lang.Object
for the field
protected IMyResource image;

The return value is used in ObjectConverterImpl to retrieve the
ClassDescriptor for the Bean:
ClassDescriptor classDescriptor =
mapper.getClassDescriptorByClass(ReflectionUtils.getBeanClass(object));

Of course there is no descriptor for java.lang.Object.

When i implement the same structure with concrete classes, OCM works fine.

The relevant technology-stack:
+ jackrabbit 1.6.0 with ocm 1.5.3
+ spring 2.5.6
+ springmodules 0.9 - with patch from
http://jira.springframework.org/browse/MOD-446
+ tomcat 6.0.18
+ cglib



How can i improve my code or maybe OCM self to get done the update-thing
with interfaces?

Any advice is welcome.

Thanks in advance,
Kadir.






Reply via email to