You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@jackrabbit.apache.org by Kadir Alaca <al...@web.de> on 2009/09/13 15:17:51 UTC
Programming against interfaces and @Bean-Fields
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.
Re: Programming against interfaces and @Bean-Fields
Posted by Kadir Alaca <al...@web.de>.
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 <al...@web.de>:
>>
>>> 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.
>>>
>>>
>>>
>>
>>
>
>
Re: Programming against interfaces and @Bean-Fields
Posted by Kadir Alaca <al...@web.de>.
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 <al...@web.de>:
>
>> 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.
>>
>>
>>
>
>
Re: Programming against interfaces and @Bean-Fields
Posted by Christophe Lombart <ch...@gmail.com>.
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 <al...@web.de>:
> 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.
>
>