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