I read that every POJO used in Groovy gets a MetaClass associated with it. These meta-classes are stored in the application wide metaclass registry. How are these meta-classes generated and placed in the meta-class registry? If each POJO gets its own meta-class, is there some sort of template that is used to generate these meta-classes?
I read that every POJO used in Groovy gets a MetaClass associated with
it.
FYI... It isn't just POJO. Every class has a meta class associate with it.
These meta-classes are stored in the application wide metaclass
registry.
That registry is represented in groovy.lang.MetaClassRegistry. You can get a reference to the registry from GroovySystem.html#getMetaClassRegistry().
How are these meta-classes generated and placed in the meta-class
registry?
There is no one way. You can write your own custom meta class and register it, Groovy registers default meta classes, you could replace a metaClass in the registry momentarily (while a unit test runs, for example) and then replace it with the original one after.
At runtime you could use methods like MetaClassRegistry.html#getMetaClass(java.lang.Class), MetaClassRegistry.html#setMetaClass(java.lang.Class,groovy.lang.MetaClass), and MetaClassRegistry.html#removeMetaClass(java.lang.Class) to manipulate the registry.
If each POJO gets its own meta-class, is there some sort of template
that is used to generate these meta-classes?
docs.groovy-lang.org/latest/html/api/groovy/lang/MetaClass is the closest thing to a template but aside from satisfying standard compile time restrictions of having to implement all the abstract methods, there could be any arbitrary logic in a meta class one might write.
Related
i am using jaxb to generate code from an xsd.
The generated code contains a lot of annotations; for classes and fields.
I am trying to use com.sun.tools.internal.xjc.Plugin to modify the generated code.
In the plugin run() method we are given an Outline class from which we can get ClassOutline. ClassOutline has an JDefinedClass final member which has the info about actual class which will be generated.
If i want to add anything, there are apis in JDefinedClass which can be used. But if i want to remove something, there is no way.
e.g. i cannot clear annotations, because the JDefinedClass.annotations() method returns an UnmodifiableCollection. so i cannot clear it or remove anything from it.
i tried to create another JDefinedClass by invoking the _class method but the ClassOutline.implClass variable is final, so i cannot set it.
how to get a JDefinedClass which does not have any annotations?
is there another phase of code generation which i can trap into to really control the generation of JDefinedClass?
The code model is, indeed mostly "write only". But, speaking of annotations, you have probably missed the methods like com.sun.codemodel.JDefinedClass.removeAnnotation(JAnnotationUse) and com.sun.codemodel.JMethod.removeAnnotation(JAnnotationUse) (implemented from com.sun.codemodel.JAnnotatable.removeAnnotation(JAnnotationUse)).
So they're there. You can remove annotations with the normal CodeModel API.
As I can see, you can also remove fields and methods from classes. So what exactly are you missing?
JDefinedClass.annotations() It return an unmodifiable collection object and you cannot modify them.
So work around for this, you can restrict annotation addition/deletion at class and field level before building JCodeModel.
You need to create a custom Jackson2Annotator class which extends Jackson2Annotator and override their methods according to your requirement.
Following are few methods which are being used for specific type of annotation property:
propertyOrder(OTB JsonPropertyOrder)
propertyInclusion(OTB JsonInclude)
propertyField(can be used for custom defined annotation at field level)
More you can discover by looking Jackson2Annotator class what fit into your need.
I have a 'document' table (very original) that I need to dynamically subset at runtime so that my API consumers can't see data that isn't legal to view given some temporal constraints between the application/database. JOOQ created me a nice auto-gen Document class that represents this table.
Ideally, I'd like to create an anonymous subclass of Document that actually translates to
SELECT document.* FROM document, other_table
WHERE document.id = other_table.doc_id AND other_table.foo = 'bar'
Note that bar is dynamic at runtime hence the desire to extend it anonymously. I can extend the Document class anonymously and everything looks great to my API consumers, but I can't figure out how to actually restrict the data. accept() is final and toSQL doesn't seem to have any effect.
If this isn't possible and I need to extend CustomTable, what method do I override to provide my custom SQL? The JOOQ docs say to override accept(), but that method is marked final in TableImpl, which CustomTable extends from. This is on JOOQ 3.5.3.
Thanks,
Kyle
UPDATE
I built 3.5.4 from source after removing the "final" modifier on TableImpl.accept() and was able to do exactly what I wanted. Given that the docs imply I should be able to override accept perhaps it's just a simple matter of an erroneous final declaration.
Maybe you can implement one of the interfaces
TableLike (and delegate all methods to a JOOQ implementation instance) such as TableImpl (dynamic field using a HashMap to store the Fields?)
Implement the Field interface (and make it dynamic)
Anyway you will need to remind that there are different phases while JOOQ builds the query, binds values, executes it etc. You should probably avoid changing the "foo" Field when starting to build a query.
It's been a while since I worked with JOOQ. My team ended up building a customized JOOQ. Another (dirty) trick to hook into the JOOQ library was to use the same packages, as the protected identifier makes everything visible within the same package as well as to sub classes...
We use early-bound class for development. But occasionally we use attribute names.
There is a way to do it using reflections, but reflections are not allowed in sandbox plugins.
What are the approaches to getting an attribute from proxy types without relying on reflections?
Opportunity.OpportunityId.AttributeName
You have a couple options:
You can use a RetrieveEntityMetadata to the list of attributes that the entity contains. You won't be able to use any early binding here, but you can inspect the results at run time to see what are valid attributes for the entity.
You could also create a simple utility that uses reflection to auto-generate a class or enum that contains the list of attributes before you actually deploy. Just add the class to your plugin dll and you'd have the benefits of early binding of entity attributes when developing your plugin, without having to do reflection at runtime.
I've been using Metro and have come across a problem whereby wsgen seems to ignore any JAXB annotation that I put on web method response classes.
I'm trying to return a set of entity classes that I want to expose to external clients via a web service, however I only want to make certain class attributes and methods visible to external clients, so have set the class access type to be PROPERTY, and have annotated all attributes I want to be part of the XML version of the class with #XmlElement.
I can create the XML schema for the entity class using the schemagen ant task, which correctly ignores any attribute or method that I have not annotated with #XmlElement, however when I run wsgen to create the wsdl for the web service which has a method which returns a set of the entity class, then I get a java.lang.NoClassDefFoundError. This appears to be because wsgen is not ignoring a public method on the entity class that it should do, with the class referenced by the exception being a parameter to this method.
I've tried to annotate the method with #XmlTransient so that wsgen ignores it, but to no avail. If anyone can suggest what I should do to get wsgen to pay attention to my annotations then that would be great.
An annotated field/property will always be processed regardless of accessor type. You need to specify #XmlAccessorType(XmlAccessType.NONE) if you only want annotated fields/properties to be treated as mapped.
For More Information
http://blog.bdoughan.com/2012/04/jaxb-and-unmapped-properties.html
I created a plain Groovy class (i.e Person class)with some properties. Now I want to get those declared attributes (which I've defined in my class) with their order, but I don't know how to do it.
I've tried to use Person.metaClass.getProperties() but it retrieves not only declared properties but also built-in Groovy ones.
Could you please help me on this: just get declared properties by its order when declaring.
Thank you so much!
I can't see a use case, but the compiler could reorder all fields declaration while creating bytecode. I'm pretty sure ordering is not a constraint on fields though it should mostly be the case for not modified/enhanced class
As per the JVM spec, generated fields should be marked SYNTHETIC (like generated methods) in the bytecode, so you can test with :
Person.getDeclaredFields().grep { !it.synthetic }
and filter the base Groovy fields like ClassInfo,metaClass and others beginning by __timestamp
But I'm not a specialist, there could be another way I don't think of
There was a question about this on the mailing list back in February of this year
The answer is, no. There is no way to get properties in the order they are declared in the class without doing some extra work.
You could parse the source file for the class, and generate an ordered list of property names from that
You could write a custom annotation, and annotate the fields with this annotation ie: #Order(1) String prop
You could make all of the classes where this matters implement an interface which forces them to have a method that returns the names of the properties in order.
Other than that, you probably want to have a re-think :-(