How can I marshal an X500Principal with JAXB? - jaxb

The class javax.security.auth.x500.X500Principal is final and (of course) not annotated with JAXB annotations? So how can I marshal it as part of a larger object graph? I would like to substitute it with the value of it's name property.
Edit
The solution is straightforward:
final class X500PrincipalXmlAdapter
extends XmlAdapter<String, X500Principal> {
#Override public X500Principal unmarshal(String name) {
return new X500Principal(name);
}
#Override public String marshal(X500Principal principal) {
return principal.getName();
}
}
Actually, I wonder why JAXB lets me get away with a non-public XMLAdapter class, but I certainly prefer it that way.

You could use an XmlAdapter for this use case. The XmlAdapter is used to convert an unmappable object into a mappable one. The XmlAdapter is configured on a field/property using the #XmlJavaTypeAdapter annotation.

Related

Can I use a no-arg constructor with Hazelcast Portable?

The Hazelcast documentation on their Portable serialization mechanism says that you are not forced to use a no-arg constructor.
https://hazelcast.org/mastering-hazelcast/#serialization-start
But their example code shows fields being set directly.
#Override
public void readPortable(PortableReader reader) throws IOException {
System.out.println("Deserialize");
this.name = reader.readUTF("name");
}
and the factory used to create instances of the class being deserialized is using a no-arg constructor.
#Override
public Portable create(int classId) {
switch (classId) {
case PERSON_CLASS_ID:
return new Person();
}
return null;
}
Am I right in assuming that you are not forced to use a no-arg constructor but you can't use it to set field values when deserializing? How would you handle enforcing invariants such as never-null fields and how would you deserialize a subclass without making the fields in the superclass protected?
While deserializing you can't maintain invariants since the object is being reconstructed; so some fields are just not set. There is no point resisting this.
And you are not forced to have a no-arg constructor. As long as the factory can create an instance, HZ doesn't care how you create it.

jaxb getter with parameter

I've requirement where I've to pass a parameter in the getter method(in my case another object). Wondering if thats possible and how can I achieve this? I'm implementing jaxws and this is my server side requirement. When client is created, getMetaValues(..) method is not available.
my code is
#XmlRootElement
#XmlAccessorType( XmlAccessType.PROPERTY)
public class Revision implements Serializable {
//other props and getter/setter
private List<Metavalue> metaValues;
#XmlElement
//Field is a custom class
public List<Metavalue> getMetaValues(Field field) {
metaValues=null;
if (field!=null) {
Map<String, Metakey> metadata = getMetadata();
Metakey metakey = metadata.get(field.getName());
if (metakey!=null) {
metaValues = metakey.getMetavalues();
}
}
return metaValues;
}
}
Thank you.
JAXB (JSR-222) implementations require a get method with no parameters. You could specify #XmlAccessorType(XmlAccessType.FIELD) so that JAXB deals directly with the field instead.

Groovy AST - Adding annotations at compilation

I'm trying to dynamicly crate an annotation that will dynamicaly add an #XmlElement annotation to every field in a class using metaprogramming and AST. I'm having problems creating the annotations and applying them to the fields properly.
The code i have is formatted here: http://pastebin.com/60DTX5Ya
import javax.xml.bind.annotation.XmlElement
#GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
class WebserviceAnnotationModifier implements ASTTransformation {
#Override
void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {
if (!astNodes) return
if (!astNodes[0] || !astNodes[1]) return
if (!(astNodes[0] instanceof AnnotationNode)) return
if (!(astNodes[1] instanceof ClassNode)) return
ClassNode node = (ClassNode)astNodes[1]
List fields = node.getFields()
fields.each {FieldNode field ->
field.addAnnotation(ClassHelper.make(new XmlElement.DEFAULT()));
}
}
}
#Retention(RetentionPolicy.SOURCE)
#Target([ElementType.TYPE])
#GroovyASTTransformationClass(classes =[WebserviceAnnotationModifier])
public #interface WebresourceAnnotation{}
#WebresourceAnnotation
class TestPerson{
String name;
String lastName;
int Age
}
Am i approaching this all wrong? The reason i do this is i have a domain that is still in the making and i'd like to just go in and apply the annotation to all fields. Couldn't find any examples of annotations added during compilation. Is this not possible?
Writing codes using Groovy AST Transformation alone does not work with the Grails reloading mechanism. Here's a proper way to implement AST transformation for a Grails app.
Your transformer class must extends AbstractGrailsArtefactTransformer.
Your transformer class must be annotated by #AstTransformer.
You class must be put under org.codehaus.groovy.grails.compiler or its sub-package. In my case I use org.codehaus.groovy.grails.compiler.zk and it's working fine.
Implement shouldInject() to match only classes you want, in this case domain classes.
Override performInjection() and write your codes there.
Pack your transformer and releated classes into a .jar file, or Grails compiler does not load it.

Programmatically determine if a JAXB annotation will result in a xsi:type annotation?

Reflecting on JAXB annotated objects, is there a way to determine if a class/field/method will result in a xsi:type attributed during marshaling?
Is XmlElement annotation,
annotation.type != javax.xml.bind.annotation.XmlElement.DEFAULT.class
the only case I need to worry about?
I'm writing a Lua unmarshaler where we have dropped much of the usual xml type info and I'm trying to figure-out how to match the incoming Lua to JAXB.
Thanks.
--Update--
Here is simple example that shows the problem:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement()
#XmlSeeAlso({ Cat.class, Dog.class })
public class Animal {
#XmlElement()
public List<Animal> critters;
#XmlAttribute
public String type;
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement()
public class Dog extends Animal {
public Dog() {
this.type = "German Shepherd";
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement()
public class Cat extends Animal {
public Cat() {
this.type = "Black";
}
}
When I receive an Animal object can I query critter's annotation to detect that it should be a Dog or Cat and not an Animal?
There are a couple circumstances where a JAXB (JSR-222) implementation will write out an xsi:type attribute.
If the field/property is of type Object (or is annotated with #XmlElement(type=Object.class)) and not mapped with #XmlAnyElement(lax=true) and holds an instance of an Object that the JAXBContext has mappings for.
The default mechanism for representing inheritance will result in an xsi:type attribute to represent subclasses (see: http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.html).

Replacing factory class with CDI

I have a collection of Processor beans in my application along with a factory for creating them.
public abstract class Processor {
public Processor(String config) { .... }
public abstract void process() throws Exception;
}
public class Processor1 extends Processor {
public Processor1(String config) { super(config);..}
public void process() {....}
}
public Processor newProcessor(String impl, String config) {
// use reflection to create processor
}
Can I use CDI to replace the factory class/method? And instead use a #Produces?
I tried using the following to iterate or select the instance I wanted. But Weld tells me that allProcessorInstances.isUnsatisfied() == true. I had to create default no-args ctor in order for Weld to find my Processor subclasses.
#Inject #Any Instance<Processor> allProcessorInstances;
Is there any way to tell the CDI container to use the constructor I want it to use? Or am I thinking about this problem the wrong way?
To use the constructor you'd need to annotate it with #Inject, however, every param on the constructor must itself be a bean or something in the CDI scopes.
Using a producer method and having that take an InjectionPoint as a param, then having your configuration be part of an annotation would work.

Resources