Hi Faizel,

Accessing metadata from cgen is a long-standing task [1]. And I
finally made an approach to it and unshelved some code I've been
working on [2]. It does exactly as you think it should, exporting
"metadataUtils" to the Velocity context, see [3] as an example.

[1] https://issues.apache.org/jira/browse/CAY-2338
[2] https://github.com/apache/cayenne/pull/422
[3] 
https://github.com/apache/cayenne/pull/422/files#diff-f4dfa761f5ec173dacb042c857cd7708R53

On Tue, May 5, 2020 at 8:43 PM Faizel Dakri <list...@dakri.com> wrote:
>
> Accessing metadata from my Cayenne app is not an issue at the moment—I am 
> doing the same thing you suggest and providing the default metadata class. 
> That works well, and I’m able to store/retrieve metadata other than comments. 
> However, it appears that metadata, specifically DataChannelMetaData, is not 
> accessible when running cgen, and by extension my entity templates. And I 
> cannot find a way to get access to it from my own tool.
>
> Cayenne is fairly new to me, so I may not know what I’m talking about, 
> however, it seems to me like the metadata cannot be accessed from cgen or any 
> velocity tool. Unless I’m missing something, there’s no way to access the 
> runtime instance (or injector) in cgen, either of which is sufficient to get 
> access to the metadata instance. I would think the easiest way to make 
> metadata available to templates is by making the DataChannelMetaData instance 
> available to the velocity context (e.g. channelMetaData) as a root object 
> (perhaps in EntityArtifact’s postInitContext), that way it can be passed to 
> any tool that needs it.
>
> F
>
>
> > On May 5, 2020, at 10:05 AM, John Huss <johnth...@gmail.com> wrote:
> >
> > For accessing the metadata, I looked into this a bit. At runtime in an app
> > this information isn't accessible by default, so if you wanted to use it at
> > runtime you would have to configure the runtime to access it with a DI
> > module like this:
> >
> > *public* *class* MyModule *implements* Module {
> >
> > *public* *void* configure(Binder binder) {
> >
> >        binder.bind(HandlerFactory.*class*).to(ExtensionAwareHandlerFactory.
> > *class*);
> >
> >        binder.bind(DataChannelMetaData.*class*
> > ).to(DefaultDataChannelMetaData.*class*);
> >
> >        ProjectModule.*contributeExtensions*(binder)
> >
> >        .add(InfoExtension.*class*);
> >
> > }
> >
> > }
> >
> >
> > Then you can get the metadata like so:
> >
> >
> > DataChannelMetaData metadata = localRuntime
> > .getInjector().getInstance(DataChannelMetaData.*class*);
> >
> > String comment = ObjectInfo.*getFromMetaData*(metadata, attribute,
> > ObjectInfo.*COMMENT*);
> >
> >
> > In an entity template for cgen that part is all you need. Coding these two
> > lines directly in a template is difficult and ugly, so this would be a good
> > place to use a custom velocity tool to simplify this API.
> >
> >
> > COMMENT is the only metadata type defined currently, but I would bet you
> > could add your own, although I don't know if Modeler would preserve them if
> > you use it for editing.
> >
> >
> >
> >
> >> On Tue, May 5, 2020 at 1:13 AM Faizel Dakri <list...@dakri.com> wrote:
> >>
> >> No worries. I never did find a way to pass properties to the cgen goal in
> >> the plugin, so I ended up experimenting with the plugin source and modified
> >> it to allow specifying system properties from the pom.xml file (in the
> >> goal’s configuration section).
> >>
> >> Once the plugin was able to set system properties, it was relatively
> >> painless to get cgen to pick up my new tool using maven (I just had to
> >> specify it as a dependency in the cayenne plugin declaration in my
> >> application’s POM)—no need to muck with classpaths explicitly, thankfully.
> >>
> >> After all this, I still can’t find a way to access the metadata from
> >> within my own tool. I am starting to think that it can only be done by
> >> supplying the metadata (e.g. metaDataUtils) from the ClassGenerationAction
> >> class.
> >>
> >> Thanks again for the pointers.
> >>
> >> F
> >>
> >>
> >>>> On May 4, 2020, at 9:56 AM, John Huss <johnth...@gmail.com> wrote:
> >>>
> >>> Unfortunately I'm not a maven user, so I can't really help here. But
> >>> hopefully someone else could chime in.
> >>>
> >>>> On Sun, May 3, 2020 at 11:39 AM Faizel Dakri <list...@dakri.com> wrote:
> >>>>
> >>>> Hi John,
> >>>>
> >>>> Thank you for the pointers. I didn’t see any way to easily get the
> >>>> metadata into my templates via a custom tool, however I thought it
> >> would be
> >>>> a good exercise to figure out how to do it anyway. I’ve tried to follow
> >>>> your advice (as well as looking at the cayenne source),   but I’m having
> >>>> difficulty getting my properties file loaded via the
> >>>> org.apache.velocity.tools property.
> >>>>
> >>>> I’m running cgen via my maven build and I can confirm the cgen goal is
> >>>> running (I can see that it is picking up my custom templates), however
> >> I’ve
> >>>> been unsuccessful in getting it to pick up my custom properties file
> >> where
> >>>> my tool is specified.  Is there a sanctioned way of telling the cgen
> >> goal
> >>>> about this property?  I’ve tried using both the maven properties plugin
> >> and
> >>>> passing on the command line, but I have yet to succeed in loading my
> >> file.
> >>>> At least it appears unsuccessful. When I debug my maven build, I see
> >> that
> >>>> there is an unresolved reference for my tool when velocity is
> >> processing my
> >>>> templates.
> >>>>
> >>>> Assuming I’m eventually successful in loading my properties, I have one
> >>>> more question. You mention that any custom velocity tool (and properties
> >>>> files) must be on the class path. I’m assuming that this is the class
> >> path
> >>>> in effect while the cgen goal is running. How does one go about altering
> >>>> the class path for a maven plugin? Or does the plugin pickup the project
> >>>> dependencies? (Apologies if this is a basic question, I’m not yet a
> >> Maven
> >>>> expert).
> >>>>
> >>>> Thanks again for your help,
> >>>>
> >>>> F
> >>>>
> >>>>
> >>>>>> On Apr 29, 2020, at 02:14 PM, John Huss <johnth...@gmail.com> wrote:
> >>>>>
> >>>>> I haven't used the metadata / comments yet, so I can't help with that
> >>>>> specifically.
> >>>>>
> >>>>> For the using a custom tool with cgen you need to define a
> >>>>> "tools.properties" file in your class path (I would just put it at the
> >>>>> root) with contents like this:
> >>>>>
> >>>>>
> >>>>> tools.toolbox = application
> >>>>>
> >>>>> tools.application.*myUtils* = com.something.tools.MyCgenUtils
> >>>>>
> >>>>>
> >>>>> The referenced class (and the properties file) needs to be on the class
> >>>>> path when you invoke cgen. The class should contain public instance
> >> (not
> >>>>> static) methods in bean-style that work on parts of the DataMap, like
> >> an
> >>>>> ObjEntity or a ObjAttribute (or their properties). For example:
> >>>>>
> >>>>>
> >>>>> *public* *boolean* hasReverse(ObjRelationship rel) {}
> >>>>>
> >>>>> Then when you invoke cgen you need to set a system property to point to
> >>>> the
> >>>>> location of your tools.properties file, like this if it is in the class
> >>>>> path root:
> >>>>>
> >>>>> -Dorg.apache.velocity.tools=/tools.properties
> >>>>>
> >>>>>
> >>>>> Your template can reference an instance of your util class using the
> >>>> short
> >>>>> name defined for it in the tools.properties file:
> >>>>>
> >>>>>
> >>>>> ${*myUtils*.getGwtType($attr.Type)}
> >>>>>
> >>>>>
> >>>>> This process has multiple points of failure, so it can be hard to
> >>>>> setup correctly, but hopefully you can get it working.
> >>>>>
> >>>>>> On Wed, Apr 29, 2020 at 11:29 AM Faizel Dakri <list...@dakri.com>
> >> wrote:
> >>>>>
> >>>>>> Hello all,
> >>>>>>
> >>>>>> Being fairly new to Cayenne, this may be an obvious question. I would
> >>>> like
> >>>>>> to know how I can access the metadata stored on an
> >>>>>> attribute/relationship/entity in the datamap from within my velocity
> >>>>>> templates (I think in CayenneModeler, this is how the comment field is
> >>>>>> stored for a datamap item). I think this is the metadata stored via
> >> the
> >>>>>> newish InfoExtension facility.
> >>>>>>
> >>>>>> I see that the DataChannelMetaData can be injected into a DataDomain
> >>>> (and
> >>>>>> I’m doing that at runtime in my server app), however I cannot see how
> >> to
> >>>>>> get to this metadata from an attribute or relationship or entity in
> >> the
> >>>>>> context of a velocity template. Is this possible? I would think it is
> >>>> since
> >>>>>> Modeler is able to read/write those comments, but I am having a hard
> >>>> time
> >>>>>> doing so in a template.
> >>>>>>
> >>>>>> I did see that there is a hook to provide my own tool into the cgen
> >>>> tool.
> >>>>>> Would this be a potential path to look into if the metadata is not
> >>>>>> accessible directly in the templates as is? If so, any pointers on
> >>>> where to
> >>>>>> start?
> >>>>>>
> >>>>>> Thanks for any advice.
> >>>>>>
> >>>>>> F
> >>>>>>
> >>>>>> --
> >>>>>> Faizel Dakri
> >>>>>> list...@dakri.com
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>
> >>>>
> >>
>


-- 
Best regards,
Nikita Timofeev

Reply via email to