Hi Dan,
> You haven't said, exactly, what your problem is... ?;
The problem that we have is that we need to show an objecto ValueObject as
a property of an entity and the wicket is no being able to explore it.
In this case, ContactVO have 3 attributes with a String type: Telephone,
Adress, email.
While we were trying to work we the solution you gave us I got stuck with
this error:
@Override
public ApplicationAdvice appliesTo(final IModel<?> model) {
if (!(model instanceof ScalarModel)) {
return ApplicationAdvice.DOES_NOT_APPLY;
}
final ScalarModel scalarModel = (ScalarModel) model;
scalarModel.getTypeOfSpecification().
return
appliesIf(ContactoVO.class.isAssignableFrom(scalarModel.getTypeOfSpecification().getUnderlyingClass());
}
the method getUnderlyingClass() is not part of getTypeOfSpecification()
I was searching in the web and it seems to be a method of this class:
com.google.api.client.util.ClassInfo;
But I still can't work on it by the way you suggest...
Hope you can help us to close this implementation.
Regards
2013/10/2 Dan Haywood <[email protected]>
> within...
>
>
> On 2 October 2013 03:45, Ezequiel Celiz <[email protected]> wrote:
>
> >
> > [snip] I would like you to take a look to the
> > things that we tried to do to show the object ContactVO with wicket
> viewer.
> >
> > We based on the structure of the component BookmarkedPages [snip]
> >
> > we create this files in this location webapp/src/main/java/app
> >
> > * ContactVOPagePanelFactoryRegistrar.java
> > * ContactVOPagePanelFactory.java
> > * ContactVOPagePanel.java
> > * ContactVOPagePanel.html
> >
> >
> That looks good so far.
>
>
>
>
>
> > Below I'll write you each class in detail:
> >
> > ////////////////////////////////////////////////////
> > //////ContactoVOPagePanelFactoryRegistrar///////////
> > ////////////////////////////////////////////////////
> > @Singleton
> > public class ContactoVOPagePanelFactoryRegistrar extends
> > ComponentFactoryRegistrarDefault {
> > @Override
> > public void addComponentFactories(ComponentFactoryList
> componentFactories)
> > {
> > componentFactories.add(new ContactVOPagePanelFactory());
> > super.addComponentFactories(componentFactories);
> > }
> > }
> >
> >
> That looks ok. You possibly want to rename the class to
> "MyAppComponentFactoryRegistrarDefault" because if there were any other
> customisations, they would also be registered here.
>
>
>
> [1]
>
> http://isis.apache.org/components/viewers/wicket/customizing-the-viewer.html
>
>
>
> > In the class QuickstartApplication.java we make use of this method:
> >
> >
> >
> bind(ComponentFactoryRegistrar.class).to(ContactVOPagePanelFactoryRegistrar.class);
> >
> >
> Yup; that's correct.
>
> As an alternative to creating your own custom ComponentFactoryRegistrar,
> you can also register component factories by adding some some metadata in
> META-INF/services; Isis can then (using the ServiceLoader API)
> automatically discover the component just by it being on the classpath.
> There's some detail about this on [1] (search for the "Additional Views of
> Collections" section).
>
>
>
>
> > ////////////////////////////////////////////////////
> > ///////////ContactVOPagePanelFactory///////////////
> > ////////////////////////////////////////////////////
> >
> > public class ContactVOPagePanelFactory extends ComponentFactoryAbstract {
> >
> > private static final long serialVersionUID = 1L;
> >
> > public ContactVOPagePanelFactory() {
> > super(ComponentType.VALUE);
> > }
> >
> > @Override
> > public ApplicationAdvice appliesTo(final IModel<?> model) {
> > return appliesIf(model instanceof ValueModel);
> > }
> >
> > @Override
> > public Component createComponent(final String id, final IModel<?>
> > model) {
> > final ValueModel valueModel = (ValueModel) model;
> > return new ContactVOPagePanel(id, valueModel);
> > }
> >
> > }
> >
> >
> Um, I'm not sure what sort of model the ContactVO would get created within.
> I have a feeling it might be in a ScalarModel rather than a ValueModel.
>
> If that's the case, then your appliesTo method would need to look similar
> to that of ValuePanelFactory. However, you should also filter to make sure
> that the "payload" of the ScalarModel is of the right type, ie an
> instanceof ContactVO.
>
> @Override
> public ApplicationAdvice appliesTo(final IModel<?> model) {
> if (!(model instanceof ScalarModel)) {
> return ApplicationAdvice.DOES_NOT_APPLY;
> }
> final ScalarModel scalarModel = (ScalarModel) model;
> return
>
> appliesIf(ContactVO.class.isAssignableFrom(scalarModel.getTypeOfSpecification().getUnderlyingClass());
> }
>
>
> But I might be wrong about this; it is possible that your ContactVO is
> wrapped up in a ValueModel? In which case the code would still need to
> check the type of the object held within the (value) model.
>
>
>
>
> > We believe that the ComponentType that may help us to resolve our problem
> > is ComponentType.VALUE
> >
> >
> You haven't said, exactly, what your problem is... ?
>
>
>
> > ////////////////////////////////////////////////////
> > //////////////////ContactVOPagePanel///////////////
> > ////////////////////////////////////////////////////
> >
> > public class ContactVOPagePanel extends PanelAbstract<ValueModel> {
> >
> > private static final String ID_ADDRESS = "address";
> > private static final String ID_TELEPHONE = "telephone";
> > private static final String ID_EMAIL = "email";
> > private static final long serialVersionUID = 1L;
> > public ContactVOPagePanel(String id, ValueModel model) {
> > super(id, model);
> > buildGui();
> > }
> >
> > private void buildGui() {
> > //final ValueModel contactVOPagePanel = getModel();
> > final Label address = new Label(ID_ADDRESS,"address of entity");
> >
> > final Label telephone = new Label(ID_TELEPHONE,"telephone of entity);
> >
> > final Label email = new
> Label(ID_EMAIL,getModel().getObject().toString());
> > add(address);
> > add(telephone);
> > add(email);
> > }
> > }
> >
> >
>
> That creates labels, but I suspect you will want to render label/forms.
> The EntityPropertiesForm#addPropertyInColumn(...) method shows how I use
> the:
>
> getComponentFactoryRegistry().addOrReplaceComponent(container, ID_PROPERTY,
> ComponentType.SCALAR_NAME_AND_VALUE, scalarModel);
>
> to create a component to add for each name/value of an entity. I think you
> might want to do something similar.
>
>
>
>
> > ////////////////////////////////////////////////////
> > /////////////ContactoVOPagePanel.html///////////////
> > ////////////////////////////////////////////////////
> >
> > <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "
> > http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
> > <html xmlns="http://www.w3.org/1999/xhtml"
> > xmlns:wicket="
> > http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"
> > xml:lang="en"
> > lang="en">
> > <body>
> > <div>
> > <table border="0">
> > <tr>
> > <td>
> > ADDRESS:
> > </td>
> > <td>
> > <span wicket:id="address"></span>
> > </td>
> > </tr>
> > <tr>
> > <td>
> > TELEPHONE:
> > </td>
> > <td>
> > <span wicket:id="telephone"></span>
> > </td>
> > </tr>
> > <tr>
> > <td>
> > EMAIL:
> > </td>
> > <td>
> > <span wicket:id="email"></span>
> > </td>
> > </tr>
> > </table>
> > </div>
> > </body>
> > </html>
> >
> >
>
> In which case, the code here would be similar to the markup in
> EntityPropertiesForm.html:
>
> <div class="inputFormTable properties">
> <fieldset wicket:id="memberGroup" class="memberGroup
> myBlockContainer">
> <legend wicket:id="memberGroupName">[group
> name]</legend>
> <div wicket:id="properties">
> <div wicket:id="property"
> class="property">[property]</div>
> </div>
> </fieldset>
> </div>
>
>
>
>
> > Well, now some questions:
> >
> > 1) Are we taking the rigth way to succed in our goal?
> >
> >
> Definitely "on the way".
>
>
>
> > 2)If an entity needs to use a valueObject Contact, we should add the
> > property: private ContactVO contactVO;
> > What do we have to do to make the framework realizes that object type
> must
> > use the component previously registered?
> >
> >
> This is the appliesTo method. I suggest you put a conditional break point
> in one of the existing component factories (eg ValuePanelFactory,
> StandaloneValuePanelFactory) to see what model the framework gives you.
>
>
>
>
> > 3)While drawing the Panel, how do we get the information of the object
> > contactVO in order to be able of upload them in the corresponding Label?
> Is
> > this posible by using ObjectAdapter with getModel().getObject()?
> >
> >
> Yep, the contactVO pojo will be wrapped in an ObjectAdapter, from whence
> you can get to the rest of the Isis metamodel (ObjectSpecification).
> ObjectAdapter corresponds to java.lang.Object, ObjectSpecification
> corresponds to java.lang.Class.
>
>
>
>
> > Sorry for the extended mail,
> >
>
> No worries. As I was writing this reply, I was wondering myself how
> feasible this is. It is possible that you might hit a showstopper
> somewhere, or I might need to dig into things a little myself. If you want
> to create a sample application up on github, then we could work on it
> together.
>
> Cheers
> Dan
>
>
>
>
> > regards!
> >
> >
> > 2013/9/18 Luis Parada <[email protected]>
> >
> > > Thank you Dan, we are going to work with the wicket viewer, so I will
> let
> > > you know later if we get something. Best Regards.-
> > >
> > >
> > > 2013/9/18 Dan Haywood <[email protected]>
> > >
> > > > Hi Luis,
> > > > welcome to the Isis mailing list.
> > > >
> > > > But my apols to you and Ezequiel, I somehow dropped the ball and
> missed
> > > > this question.
> > > >
> > > > To answer some of your question: to get the ContactVO to persist - as
> > you
> > > > have done - it is sufficient only to make it serializable. However,
> if
> > > you
> > > > want it to be stored as something other than a blob, you'll need to
> use
> > > the
> > > > JDO APIs (eg as is done for Joda types).
> > > >
> > > > Your issue, though, is on the UI side. And, unfortunately, right now
> > > Isis
> > > > doesn't provide an out-of-the-box capability to render composite
> value
> > > > objects such as you have defined here. It most certainly ought to do
> > so,
> > > > and indeed we have a ticket for something very similar... [1] it just
> > > isn't
> > > > implemented, I'm afraid.
> > > >
> > > > The EncoderDecoder stuff won't help... that is used by some of the
> > other
> > > > object stores (eg XML, NoSQL). But it's irrelevant for Wicket/JDO.
> > > >
> > > > The main issue is that the Wicket viewer doesn't "look inside" the
> > > > structure of your ContactVO in order to build up a suitable UI. For
> > > > example, the ContactVO is basically 3 string properties, and you
> would
> > > > presumably want 3 fields. It's just not smart enough to do that.
> > > >
> > > > I can offer a possible workaround for you, if you want, which *might*
> > > work.
> > > > The Wicket viewer *is* extensible, and so you could define and
> > register
> > > > your own ContactVOComponentFactory and have it build up a custom
> > > > ContactVOComponent (a panel) for rendering the parts of the contact
> as
> > > > individual fields.
> > > >
> > > > Have a look at ComponentFactoryRegistryDefault and how some of the
> > other
> > > > ComponentFactorys work - it's basically the chain of responsibility
> > > > pattern.
> > > >
> > > > Or... alternatively you might want to generalize this, in other words
> > > > implement [1]. Note that [1] uses the AggregatedFacet as the
> indicator
> > > on
> > > > the referenced object that it should be displayed "inline". If this
> > > > reference is mapped using JDO's @Embedded, it would also save you the
> > > > hassle of doing extra JDO datatype mappings.
> > > >
> > > > HTH, come back to me if none of the above makes sense...
> > > >
> > > > Best
> > > > Dan
> > > >
> > > >
> > > > [1] https://issues.apache.org/jira/browse/ISIS-348
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > > On 18 September 2013 13:26, Luis Parada <[email protected]>
> > > > wrote:
> > > >
> > > > > Hi, I´m working on this with Ezequiel and we could persist the
> > Contact
> > > > VO.
> > > > > The problem is that we can not show the object in the viewer
> because
> > > the
> > > > > object is serialized. We found
> > > > > the public interface EncoderDecoder<T> {} wich implements this
> > method:
> > > T
> > > > > fromEncodedString(String encodedString); so we appreciate any help
> > > > > explaining us how to use it.
> > > > >
> > > > > At this moment we have overrided the methods: protected String
> > > > > doEncode(final Object object) and protected Contact doRestore(final
> > > > String
> > > > > data) of ContactoValueSemanticsProvider but is not working yet.
> > > > >
> > > > > protected String doEncode(final Object object) {
> > > > > final Contacto contacto = (Contacto) object;
> > > > > final String valor = String.valueOf(contacto.getDomicilio() + "-" +
> > > > > contacto.getEmail() + "-" + contacto.getTelefono());
> > > > > return valor;
> > > > > }
> > > > >
> > > > > protected Contacto doRestore(final String data) {
> > > > > final String[] partes = data.split("-");
> > > > > final String domicilio = partes[0];
> > > > > final String correo = partes[1];
> > > > > final String telefono = partes[2];
> > > > > return new Contacto(domicilio, correo, telefono);
> > > > > }
> > > > > Thank´s.
> > > > >
> > > > >
> > > > > 2013/9/12 Ezequiel Celiz <[email protected]>
> > > > >
> > > > > > Hi community
> > > > > >
> > > > > > I'm trying to implement the annotation @Value in my application
> to
> > > use
> > > > > the
> > > > > > "Value Objects" as defined in the concept of DDD .
> > > > > >
> > > > > > I had no success : How I can set my class as a genuine Custom
> Value
> > > > Type?
> > > > > > so that it can be used in the entities that require it.
> > > > > >
> > > > > > I want to create the classic VO : "Contact" which consists of the
> > > > > following
> > > > > > properties ( in my case) :
> > > > > >
> > > > > > Address, Telephone and Email.
> > > > > >
> > > > > > @Value ( semanticsProviderName = "
> > > > > > ContactValueSemanticsProvider.class " )
> > > > > > public class Contact {
> > > > > >
> > > > > > / *
> > > > > > / Need to the builder?
> > > > > > /
> > > > > > / Public Contact ( String a, String t , String e) {
> > > > > > / This.address = a;
> > > > > > / This.telephone = t;
> > > > > > / This.email = e ;
> > > > > > / }
> > > > > > /
> > > > > > / *
> > > > > >
> > > > > > private String address ;
> > > > > >
> > > > > > public String getAddress ( ) {
> > > > > > return address ;
> > > > > > }
> > > > > >
> > > > > > public void setAddress (String address) {
> > > > > > this.address = address ;
> > > > > > }
> > > > > >
> > > > > > private String telephone ;
> > > > > >
> > > > > > getTelephone public String ( ) {
> > > > > > return telephone ;
> > > > > > }
> > > > > >
> > > > > > public void setTelephone (String telephone) {
> > > > > > this.telephone = telephone ;
> > > > > > }
> > > > > >
> > > > > > private String email ;
> > > > > >
> > > > > > getEmail public String ( ) {
> > > > > > return email ;
> > > > > > }
> > > > > >
> > > > > > public void setEmail (String email ) {
> > > > > > this.email = email ;
> > > > > > }
> > > > > >
> > > > > > }
> > > > > >
> > > > > > where ContactValueSemanticsProvider.class :
> > > > > > public final class ContactValueSemanticsProvider
> > > > > > extends AbstractValueSemanticsProvider <Conctact> {}
> > > > > >
> > > > > > Then I wonder if the entity would have to have an attribute :
> > > > > >
> > > > > > private Contact contact ;
> > > > > >
> > > > > > public GetContact ( ) {
> > > > > > return contact ;
> > > > > > }
> > > > > >
> > > > > > Finally in the service when I creating the entity object :
> > > > > >
> > > > > > SomeEntity public newEntity (
> > > > > > @ Optional
> > > > > > @ Named ( " Address" ) String address,
> > > > > > @ Optional
> > > > > > @ Named ( " Telephone" ) String telephone ,
> > > > > > @ Optional
> > > > > > @ Named ( " email " ) String email
> > > > > > ) {
> > > > > >
> > > > > > final Contact contact
> > > > > >
> > > > > > / / The correct way to instantiate is THROUGH
> > > > > > newTransientInstance ( Contact.class ) ?
> > > > > >
> > > > > > pourContacter (contact) ;
> > > > > >
> > > > > > @ Hidden
> > > > > > SomeEntity public pourContacter ( ) (
> > > > > > Final Contact Contact
> > > > > > ) {
> > > > > > SomeEntity end someEntity = newTransientInstance (
> > > > > SomeEntity.class
> > > > > > ) ;
> > > > > > someEntitity.setContact (contact) ;
> > > > > > persistIfNotAlready ( someEntity ) ;
> > > > > >
> > > > > > someEntity return ;
> > > > > > }
> > > > > >
> > > > > > It is the right way? or the way to work with the Value Object in
> > ISIS
> > > > is
> > > > > > another?
> > > > > >
> > > > > > I welcome your suggestions
> > > > > > Thank you very much as always for your attention
> > > > > > Cheers !
> > > > > > Ezequiel
> > > > > >
> > > > >
> > > >
> > >
> >
>