Moxy: marshall without JAXB annotations like #XmlRootElement - moxy

Is it possible to marshall all Java POJOs to XML without using JAXB annotations without configuring every POJO class independently?
PS: the context is a Rest Resource with Jersey 2.

JAXB (JSR-222) implementations including MOXy do not require any annotations. In the absence of an #XmlRootElement annotation you need to wrap your object in an instance of JAXBElement.
JAXBContext jc = JAXBContext.newInstance(Foo.class);
Foo foo = new Foo();
JAXBElement<Foo> je = new JAXBElement(new QName("root-element"), Foo.class, foo);
Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(je, System.out);
For More Information
You can refer to the following article from my blog for a full example:
http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html

Related

how to use Jackson to deserialize a map property without the Annotation #JsonDeserialize

I have to deserialize a Class in third-party jar that contains a Map<String,Object> Collection property, so that the Annotation #JsonDeserialize cannot be used to defined at the property level,
I find that ObjectMapper can be registered with the custom deserializer, like
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(X.class, new XDeserializer());
mapper.registerModule(module);
X x = mapper.readValue(json, X.class);
but this is for class, is there any way to register a custom deserializer for property?

Can we access spring bean in Karate feature?

I have a class like below, can I access the myServer object or call handleOperation() method (which can use the injected bean) in Karate Feature file? If yes then may I know how?
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {MyApiApp.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ContextConfiguration(classes = {AcceptanceTestConfiguration.class})
#ActiveProfiles("test")
#KarateOptions(features = "classpath:acceptanceTest/api/myapi.feature", tags = "#myapi")
public class MyAtddTest {
#Autowired
private MyServer myServer;
public void handleOperation() throws Exception {
myServer.handle();
}
}
There is no direct support for spring or the annotations. And not sure if you can mix the test annotations.
But take a look at the Spring MVC Dispatcher example here: https://github.com/intuit/karate/tree/master/karate-mock-servlet#mocking-your-servlet
Specifically how using Java interop you can do anything you want. I recommend getting the spring context using first-principles. For e.g:
ApplicationContext context = new AnnotationConfigApplicationContext(AcceptanceTestConfiguration.class);
And then getting beans out of it. Setting a test profile via System.setProperty() should be simple, search for it. You can do all this in even the karate-config.js and then it should be easy to use from all Scenario-s.
EDIT - also refer: https://github.com/Sdaas/hello-karate

Register JodaModule in Jax-RS Application

I'm writing a Jax-RS application using Jersey, and Jackson2 under the hood to facilitate JSON i/o. The service itself works fine, but I'd like to improve it by having the Jackson mapper automagically serialize/deserialize date and date-times to JodaTime objects.
I'm following the documentation here and have added the relevant jars, but I'm lost on this instruction:
Registering module
To use Joda datatypes with Jackson, you will first need to register the module first (same as with all Jackson datatype modules):
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());
I've tried to do this in the custom class that extends jax.ws.rs.core.Application, but I'm not at all confident in that solution. I'm currently getting this error:
Can not instantiate value of type [simple type, class org.joda.time.DateTime] from String value ('2014-10-22'); no single-String constructor/factory method
at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream#3471b6d5; line: 7, column: 25]
Other than the general impression that this module registration needs to happen at application (servlet?) startup, I have no idea what to do with this information. Do I need to annotate a custom class with something in particular to have it picked up ? Should I be extending some class ?
The examples I find on StackOverflow usually stick it in main() and call the mapper directly, but I'm relying on Jackson Databinding so the examples aren't relevant. Any direction is appreciated.
You'll basically want to create/configure/return the ObjectMapper in a ContextResolver. Something like
#Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
final ObjectMapper mapper = new ObjectMapper();
public ObjectMapperContextResolver() {
mapper.registerModule(new JodaModule());
}
#Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
If you are using package scanning to discover your resources, then the #Provider annotation should allow this class to be discovered and registered also.
Basically what happens, is the the MessageBodyReader and MessageBodyWriter provided by Jackson, used for unmarshalling and marshalling, respectively, will call the getContext method in the ContextResolver, to determine the ObjectMapper to use. The reader/writer will pass in the class (in a reader it will be the type expected in a method param, in a writer it will be the type returned as-a/in-a response), meaning we are allowed to use differently configured ObjectMapper for different classes, as seen here. In the above solution, it is used for all classes.

Javassist overwriting existing annotations

Already existed annotations present at the top of class are removing and whatever i added using Javassist are adding but not taking any effect.
suppose
#Entity
class Master
{
//variables
//getters and setters
}
What i need is to add extra annotation #Table(name="Master",schema="Master_Database")
to be added via Javassist dynamically to the above class 'Master'.
What i'm facing is #Entity is removed and #Table is successfully added.
This causes loss of functionality of eclipseLink auto generation of entity classes.
Plz help me
It should be as simple as:
ctClass.getClassFile().addAttribute(attributeInfo);
That should not remove existing annotations. For helping you further we would need to know how you added the annotation.
But are you bound to Javassist? Have a look at Byte Buddy (I am the author) which makes adding annotations a rather easy excercise:
TypePool pool = TypePool.Default.ofClassPath();
TypeDescription type = pool.describe("name.of.class");
Class<?> enhanced = new ByteBuddy()
.redefine(type, ClassFileLocator.ForClassFile.ofClassPath())
.annotation(new Table() {
...
})
.make()
.load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();

Jackson unrecognized field exception but field is in JSON

I am using Spring Integration to consume a message with a JSON Payload.
In my spring context I have
<integration:channel id="jsonToMyMessageConverterChannel"/>
<integration:json-to-object-transformer
type="com.acme.messaging.message.MyMessage"
input-channel="jsonToMyMessageConverterChannel"
output-channel="myMessageUpdateChannel"/>
My message related objects are:
MyMessage.java
#JsonIgnoreProperties(ignoreUnknown=true)
public class MyMessage {
#JsonProperty
private String timestamp;
#JsonProperty("msgs")
private List<Message> messages;
// Getters and Setters...
}
Message.java
#JsonIgnoreProperties(ignoreUnknown=true)
public class Message {
#JsonProperty
private Integer msgId;
#JsonProperty("msgText")
private String text;
// Getters and Setters...
}
When the json transformer attempts to convert the message to an object it fails with
Caused by: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "msgs" (Class com.acme.messaging.message.MyMessage), not marked as ignorable
The JSON payload definitely has msgs which is an array that has objects which represent the Message.java class.
Can any one suggest reasons why the exception occurs given that the JSON has the field that is being complained about and the class itself is also annotated to ignore unknown fields?
Update
After some debugging it looks like the #JsonProperty("msgs") annotations aren't being use, for some reason.
This works fine for me...
#Test
public void test() throws Exception {
MyMessages mm = new MyMessages();
MyMessage m = new MyMessage();
m.setMsgId(1);
m.setText("foo");
mm.setMessages(Arrays.asList(m));
mm.setTimestamp("123");
#SuppressWarnings("deprecation")
ObjectToJsonTransformer otjt = new ObjectToJsonTransformer(new ObjectMapper());
Message<?> message = new GenericMessage<MyMessages>(mm);
message = otjt.transform(message);
System.out.println(message);
#SuppressWarnings("deprecation")
JsonToObjectTransformer<MyMessages> jtot = new JsonToObjectTransformer<MyMessages>(MyMessages.class, new ObjectMapper());
message = jtot.transform(message);
mm = (MyMessages) message.getPayload();
System.out.println(mm.getTimestamp());
System.out.println(mm.getMessages().get(0).getText());
}
(I changed your classnames slightly to avoid colliding with Message<?>)
Resulting in...
[Payload={"timestamp":"123","msgs":[{"msgId":1,"msgText":"foo"}]}][Headers={timestamp=1373997151738, id=f2425f36-a500-4aee-93a4-e7e0240ce0f1, content-type=application/json}]
123
foo
Do you have both jackson 1.x (codehaus) and 2.x (fasterxml) on the classpath, and using Spring Integration 3.0.0?
If they're both on the classpath, SI will use Jackson 2.x, by default, (which won't understand 1.x annotations).
Or, I guess - are you using Jackson2 (fasterxml) annotations? Spring Integration 2.x uses Jackson 1 (codehaus).
EDIT:
In order to support both versions of Jackson, you can annotate the class with both annotations...
#JsonProperty("msgs")
#com.fasterxml.jackson.annotation.JsonProperty("msgs")
public List<MyMessage> messages;