You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@isis.apache.org by Kevin Meyer <ke...@kmz.co.za> on 2011/03/17 10:20:44 UTC
How do I directly create/initialise an ObjectAdapter?
Dan, Rob?
In the SQL object store AbstractJdbcFieldMapping, the method
"public void initializeField(ObjectAdapter object, Results rs)"
explicitly converts the record set field into a string, then uses
"field.getSpecification().getFacet(EncodableFacet.class).fromEncodedString(valueString)"
to create an object adapter from the string.
This is quite messy and obviously will kill anything like a BLOB (e.g. an
image!)
How do I directly create (for example) an ObjectAdapter containing an Isis
applib Date value, to pass on to
"((OneToOneAssociation) field).initAssociation(object, restoredValue);"
I guess the real requirement is creating the ObjectAdapter (for the
retrieved value object) to pass on to "initAssociation".
The same would go for the other values (e.g. Image), and extend to custom
written value types (ValueSemanticsProvider? but I see that being handled
by an AbstractJdbcFieldMapping class implementation).
In short - I am trying to move away from fetching/storing properties as
strings. This started with recoding the Sql object store to use prepared
statements with inserted objects (e.g. WHERE value = ?) instead of (WHERE
value = 'zorkmid').
Regards,
Kevin
Re: How do I directly create/initialise an ObjectAdapter?
Posted by Dan Haywood <dk...@gmail.com>.
On 17/03/2011 18:47, Kevin Meyer - KMZ wrote:
>>> In the SQL object store AbstractJdbcFieldMapping, the method
>>> ...
>>> to create an object adapter from the string.
>>>
>>> This is quite messy and obviously will kill anything like a BLOB (e.g. an
>>> image!)
>> Well, not necessarily. There's nothing to prevent your value type to
>> encode itself as a string, eg using base 64 encoding.
> Eeek! Do you hear 30% data bloat? ;)
Well, any encoding will do. Base 64 is just easy, that's all.
We could, I suppose, extend ValueSemanticsProvider to support two
different types of Encoders, the current
org.apache.isis.applib.adapters.EncoderDecoder that encodes/decodes to
Strings, and another one that encodes to byte[]. The marshalling could
perhaps ask for the former, but fall back to the latter.
If you want to try a spike on it, go ahead.
>>> How do I directly create (for example) an ObjectAdapter containing an Isis
>>> applib Date value, to pass on to
>>> "((OneToOneAssociation) field).initAssociation(object, restoredValue);"
>>>
>>> I guess the real requirement is creating the ObjectAdapter (for the
>>> retrieved value object) to pass on to "initAssociation".
>> I'm not sure that you do need to do this if you use VSPs, but to answer
>> your question: you can use:
>>
>> IsisContext().getPersistenceSession().getAdapterManager().adapterFor(object).
> Thanks - I'll give this a try. I'm assuming that the following'll work:
>
> Date newDateValue = rs.getDate(columnName);
>
> ObjectAdapter restoredValue = IsisContext(). \
> getPersistenceSession().\
> getAdapterManager(). \
> adapterFor(newDateValue);
>
> ((OneToOneAssociation) field).initAssociation(object, restoredValue)
>
Yeah, sounds about right.
Dan
PS: as you saw a few weeks ago, I've moved all this stuff into
runtimes.dflt (previously it was in core.runtime). That's because I
want to allow for other runtime implementations, that perhaps have less
moving parts and leverage more existing stuff, eg JDO 3.0 (ISIS-14), or
even very simple pojos that wrap maps and that are persisted as JSON in
Mongo/Couch. I see these alternative runtime implementations as
supporting adapters just by new'ing up, ie new
ObjectAdapterImpl(dataValue) ... the point would mostly be to provide
access into the ObjectSpecification (ie metamodel).
Re: How do I directly create/initialise an ObjectAdapter?
Posted by Kevin Meyer - KMZ <ke...@kmz.co.za>.
> > In the SQL object store AbstractJdbcFieldMapping, the method
> > ...
> > to create an object adapter from the string.
> >
> > This is quite messy and obviously will kill anything like a BLOB (e.g. an
> > image!)
> Well, not necessarily. There's nothing to prevent your value type to
> encode itself as a string, eg using base 64 encoding.
Eeek! Do you hear 30% data bloat? ;)
> > How do I directly create (for example) an ObjectAdapter containing an Isis
> > applib Date value, to pass on to
> > "((OneToOneAssociation) field).initAssociation(object, restoredValue);"
> >
> > I guess the real requirement is creating the ObjectAdapter (for the
> > retrieved value object) to pass on to "initAssociation".
>
> I'm not sure that you do need to do this if you use VSPs, but to answer
> your question: you can use:
>
> IsisContext().getPersistenceSession().getAdapterManager().adapterFor(object).
Thanks - I'll give this a try. I'm assuming that the following'll work:
Date newDateValue = rs.getDate(columnName);
ObjectAdapter restoredValue = IsisContext(). \
getPersistenceSession().\
getAdapterManager(). \
adapterFor(newDateValue);
((OneToOneAssociation) field).initAssociation(object, restoredValue)
> If you look at the implementation (AdapterManagerDefault) then you'll
> see that we look for a ValueFacet on the spec of the provided object.
> If so, we create a "standalone" adapter to wrap the value.
Something to keep in mind.
Thanks,
Kevin
Re: How do I directly create/initialise an ObjectAdapter?
Posted by Dan Haywood <dk...@gmail.com>.
On 06/04/2011 20:37, Kevin Meyer - KMZ wrote:
>
> Creating the applib value type first, then using the ...adapterFor(object)
> method made adding support multi-column SQL object store support
> real easy.
>
> I was able to add support for the applib.value.Money value type quite
> easily, by extending AbstractJdbcFieldMapping to create a
> "AbstractJdbcMultiFieldMapping" type - which stores "currency" and
> "value" in separate columns.
>
>
Good stuff, thanks for putting the time in on this!
Cheers
Dan
Re: How do I directly create/initialise an ObjectAdapter?
Posted by Kevin Meyer - KMZ <ke...@kmz.co.za>.
> > I guess the real requirement is creating the ObjectAdapter (for the
> > retrieved value object) to pass on to "initAssociation".
>
> I'm not sure that you do need to do this if you use VSPs, but to answer
> your question: you can use:
>
> IsisContext().getPersistenceSession().getAdapterManager().adapterFor(object).
Thanks - I have used this method with a good degree of success, see
below..
>
> If you look at the implementation (AdapterManagerDefault) then you'll
> see that we look for a ValueFacet on the spec of the provided object.
> If so, we create a "standalone" adapter to wrap the value.
>
> > The same would go for the other values (e.g. Image), and extend to custom
> > written value types (ValueSemanticsProvider? but I see that being handled
> > by an AbstractJdbcFieldMapping class implementation).
> I didn't write the AJFM, but as you've noted it's implementation is
> hard-coded to only encode to strings, and it then leverages the
> VSP#EncoderDecoder to do the heavy lifting.
Creating the applib value type first, then using the ...adapterFor(object)
method made adding support multi-column SQL object store support
real easy.
I was able to add support for the applib.value.Money value type quite
easily, by extending AbstractJdbcFieldMapping to create a
"AbstractJdbcMultiFieldMapping" type - which stores "currency" and
"value" in separate columns.
Re: How do I directly create/initialise an ObjectAdapter?
Posted by Dan Haywood <dk...@gmail.com>.
Hi Kevin,
within...
On 17/03/2011 09:20, Kevin Meyer wrote:
> Dan, Rob?
>
> In the SQL object store AbstractJdbcFieldMapping, the method
> "public void initializeField(ObjectAdapter object, Results rs)"
> explicitly converts the record set field into a string, then uses
> "field.getSpecification().getFacet(EncodableFacet.class).fromEncodedString(valueString)"
> to create an object adapter from the string.
>
> This is quite messy and obviously will kill anything like a BLOB (e.g. an
> image!)
Well, not necessarily. There's nothing to prevent your value type to
encode itself as a string, eg using base 64 encoding. What you will
need to do is to write and register a ValueSemanticsProvider for the
value type that you want to persist though (there are plenty of
implementations in the codebase to look at; basically your VSP will need
to implement getEncoderDecoder() method as a minimum).
The other thing to do is to register the VSP. If this is a custom value
type, then you can annotate it with @Value. Otherwise, you'll need to
register the VSP in isis.properties; have a look at
ValueFacetFactoryTest#testSemanticsProviderNameCanBePickedUpFromConfiguration
for details on the syntax:
isis.core.progmodel.value.com.mycompany.myapp.MyValueSemanticProvider.semanticsProviderName=com.mycompany.myapp.MyValueSemanticProvider
> How do I directly create (for example) an ObjectAdapter containing an Isis
> applib Date value, to pass on to
> "((OneToOneAssociation) field).initAssociation(object, restoredValue);"
>
> I guess the real requirement is creating the ObjectAdapter (for the
> retrieved value object) to pass on to "initAssociation".
I'm not sure that you do need to do this if you use VSPs, but to answer
your question: you can use:
IsisContext().getPersistenceSession().getAdapterManager().adapterFor(object).
If you look at the implementation (AdapterManagerDefault) then you'll
see that we look for a ValueFacet on the spec of the provided object.
If so, we create a "standalone" adapter to wrap the value.
> The same would go for the other values (e.g. Image), and extend to custom
> written value types (ValueSemanticsProvider? but I see that being handled
> by an AbstractJdbcFieldMapping class implementation).
I didn't write the AJFM, but as you've noted it's implementation is
hard-coded to only encode to strings, and it then leverages the
VSP#EncoderDecoder to do the heavy lifting.
If you wanted to have support to something else (eg Images to BLOBs),
then I think we'd need to define something equivalent mechanism to allow
values to be marshalled to other types (eg byte[]). However, only
objectstores are likely to need this, so I'd probably want us to
introduce an applib scoped to each objectstore (eg sql/applib) for these
value types. You can see I do a similar thing for Restful viewer and
Wicket viewer.
HTH
Dan
> In short - I am trying to move away from fetching/storing properties as
> strings. This started with recoding the Sql object store to use prepared
> statements with inserted objects (e.g. WHERE value = ?) instead of (WHERE
> value = 'zorkmid').
>
> Regards,
> Kevin
>
>
>