MOXy's #XmlCDATA seems to have no affect - rest

I would like to have the following returned to the browser (view source)
<content>
<![CDATA[Please show this inside a unescaped CDATA tag]]>
</content>
But I acutally get
<content>
Please show this inside a unescaped CDATA tag
</content>
If, I change the value of content to be
&lt ;![CDATA[Please show this inside a unescaped CDATA tag]]&gt ;
, the less than and the greater than for the tag are escaped.
Wondering how to achieve what I wanted????
Here is my code
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/myRequest")
public class MyRestClass {
#GET
#Path("{myPathNumber}")
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Object doInquiry(#PathParam("myPathNumber") String myPathNumber) {
try {
return new MyObject();
} catch (Exception e) {
return "exception " + e.getMessage();
}
}
}
package org.openengine.wink;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlCDATA;
#XmlRootElement
public class MyObject implements Serializable {
#XmlElement
#XmlCDATA
private String content = "Please show this inside a unescaped CDATA tag";
}
in package org.openengine.wink I have a file, jaxb.properties, with the following content
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

CLASSPATH
My best guess is that EclipseLink JAXB (MOXy) is not correctly configured on your classpath, and the JAXB RI is being used as the JAXB (JSR-222) provider in your environment.
METADATA
The EclipseLink JAXB (MOXy) metadata you have provided appears to be correct. This can be verified with the following standalone demo code.
MyObject
By default JAXB (JSR-222) implementations look for metadata on the property (getter/setter). Since you have annotated the field I would recommend using the #XmlAccessorType(XmlAccessType.FIELD annotation (see: http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html).
package org.openengine.wink;
import java.io.Serializable;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlCDATA;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class MyObject implements Serializable {
#XmlElement
#XmlCDATA
private String content = "Please show this inside a unescaped CDATA tag";
}
jaxb.properties
To specify MOXy as your JAXB provider you need to have the EclipseLink binaries on your classpath and have a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
package org.openengine.wink;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(MyObject.class);
MyObject myObject = new MyObject();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(myObject, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<myObject>
<content><![CDATA[Please show this inside a unescaped CDATA tag]]></content>
</myObject>
For More Information
http://blog.bdoughan.com/2010/07/cdata-cdata-run-run-data-run.html

Related

Wildfly throws "Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam" error

Im using wildfly 9.0 to deploy my war file. I have java LocalDateTime, Java Money types defined in my REST GET endpoints.
When i deploy my war file, i get following error[1]. Based on this answer [2] I have written "ParamConverterProvider" implementations for both types.
It was working fine( I haven't seen same issue again till now) and now i get same issue.
Any clue?
[1]
Caused by: java.lang.RuntimeException: Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam(\"totalMoneyVolumeForPeriod\") on public javax.ws.rs.core.Response com.test.rest.StockEndpoint.getItems(java.lang.Integer,java.lang.Integer,java.lang.String,java.lang.String,java.lang.Long,org.javamoney.moneta.Money,java.util.Set,java.lang.String) for basetype: org.javamoney.moneta.Money"}}}}
[2]
jaxrs could not find my custom (de)serializers for joda.money type
Sample code
package com.test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import javax.money.Monetary;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;
import org.javamoney.moneta.Money;
#Provider
public class MoneyConverterProvider implements ParamConverterProvider {
private final MoneyConverter converter = new MoneyConverter();
#Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
if (!rawType.equals(Money.class)) return null;
return (ParamConverter<T>) converter;
}
public class MoneyConverter implements ParamConverter<Money> {
public Money fromString(String value) {
if (value == null ||value.isEmpty()) return null; // change this for production
return Money.of(new BigDecimal(value), Monetary.getCurrency("AUD"));
}
public String toString(Money value) {
if (value == null) return "";
return value.toString(); // change this for production
}
}
}
Application claas
package com.test;
import javax.ws.rs.core.Application;
import com.test.autogen*;
import io.swagger.jaxrs.config.BeanConfig;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
#ApplicationPath("/rest")
public class RestApplication extends Application {
public RestApplication() {
BeanConfig beanConfig = new BeanConfig();
//beanConfig.setVersion("1.0");
beanConfig.setSchemes(new String[] { "http" });
beanConfig.setTitle("My API");
beanConfig.setBasePath("/rest");
beanConfig.setResourcePackage("com.test.autogen");
beanConfig.setScan(true);
}
#Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<Class<?>>();
set.add(EmailEndpoint.class);
set.add(StockEndpoint.class);
set.add(io.swagger.jaxrs.listing.ApiListingResource.class);
set.add(io.swagger.jaxrs.listing.SwaggerSerializers.class);
return set;
}
}
When you are using classpath scanning, JAX-RS components annotated with #Path or #Provider will get picked up and registered. There are a couple way to use classpath scanning. The most common way is to just have an empty Application class annotated with #ApplicationPath
#ApplicationPath("/api")
public class MyApplication extends Application {}
This is enough for a JAX-RS application to be loaded, and to have the application's classpath scanned to components to register.
But, per the specification, once we override any of the Set<Object> getSingletons or Set<Class> getClasses methods of the Application class, and return a non-empty set, this automatically disables classpath scanning, as it is assumed we want to register everything ourselves.
So in previous cases, you were probably just using classpath scanning. In this case, you need to explicitly add the provider to the set of classes in your getClasses method, since you overrode the method to add other component classes.

Null pointer Exception while fetching parameter value from path while trying simple rest application

The code i am trying is showing Null pointer Exception because it is not extracting parameter value from path and i am not getting why? if any one could help me out with this ??
The path value extracted from pathparam i.e is name is extracted as null and why this is happening am not getting please help me out with the same.
I am not getting at all what the problem actually is I tried and I only got that parameter value for name is not getting extracted in path param, I checked out on the different sites still am not able to get the solution. I hope posting over here helps me to find a solution
My resource class is:
package resource;
import javax.websocket.server.PathParam;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import dao.CustomerDao;
import dao.CustomerDaoImpl;
import entity.Customer;
#Path("/customer")
public class CustomerResource {
CustomerDaoImpl dao = new CustomerDaoImpl();
#GET
#Path("/greet")
public String greet(){
return("Hello World");
}
#GET
#Path("/{name}")
public String getCustomerByName(#PathParam("name") String name){
System.out.println("the name is : "+name);
return dao.getCustomerByName(name).toString();
}
}
and service class is below:
package dao;
import java.util.ArrayList;
import java.util.List;
import entity.Customer;
public class CustomerDaoImpl implements CustomerDao {
static private List<Customer> customerList = new ArrayList<Customer>();
static {
customerList.add(new Customer("John",101,"7757945607"));
customerList.add(new Customer("Joe", 102,"8857833518"));
customerList.add(new Customer("James",103,"8177998482"));
customerList.add(new Customer("Roy",104,"8149038984"));
customerList.add(new Customer("Dev",105,"9503257180"));
}
#Override
public Customer getCustomerByName(String name) {
for (Customer c : customerList) {
if (c.getCustomerName().equalsIgnoreCase(name)) {
return c;
}
}
return null;
}
}
although i am using the correct path
http://localhost:8080/CustomerWebApp/rest/customer/Roy
You are using the wrong PathParam. You should use javax.ws.rs.PathParam.
yes PathParam you have to use provided by jar-rs specification .
you have used wrong one javax.websocket.server.PathParam;
for more Details how to use #PathParam and #path annotation plz refer:http://entityclass.in/rest/jaxRsAnnotationPath.htm

JAXB 'forgets' to add nil='true' when attribute value is set, but element value is not

We use Jaxb (jaxb-api 2.2.5) to generate a Java class from an XSD. The 'someField' element has a nillable='true' attribute and an (implicit) minoccurs='1'. There is also an optional 'order' attribute.
When we set the order attribute on someField, but no value, JAXB will generate the XML element in the request without nill='true' and this is not accepted by the XSD and results in a SOAP fault.
The XSD for the field:
<xs:element name="someField" nillable="true">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="iata:AlphaNumericStringLength1to19">
<xs:attribute name="order" type="xs:integer" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
Jaxb translates this to the following field on our Java class:
#XmlElement(required = true, nillable = true)
protected SomeParentType.SomeField someField;
The SomeField class looks like this:
public static class SomeField{
#XmlValue
protected String value;
#XmlAttribute
protected BigInteger order;
// getters + setters
}
When we set the order ATTRIBUTE to 2 (for example), and set nothing for the value, JAXB will generate this:
<pay1:someField order="2"/>
This is not valid according to the XSD and it results in a SOAP fault when we send it.
This does work:
<pay1:someField xsi:nil="true" order="2"/>
Do you know how we can get JAXB be to generate the latter? And is JAXB actually wrong in generating the nil-less version?
And is JAXB actually wrong in generating the nil-less version?
Let me get back to you on this.
Do you know how we can get JAXB be to generate the latter?
Below is what you can do
Java Model
SomeParentType
To get the behaviour you are looking for with existing JAXB libraries the domain model needs to be of the following form:
import java.math.BigInteger;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
#XmlRootElement
public class SomeParentType {
#XmlElementRef(name="someField")
protected JAXBElement<SomeParentType.SomeField> someField;
public static class SomeField{
#XmlValue
protected String value;
#XmlAttribute
protected BigInteger order;
// getters + setters
}
}
Registry
To go along with the #XmlElementRef we need to have an #XmlElementDecl on a class annotated with #XmlRegistry.
import javax.xml.namespace.QName;
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
#XmlRegistry
public class Registry {
#XmlElementDecl(name="someField")
public JAXBElement<SomeParentType.SomeField> createSomeField(SomeParentType.SomeField someField) {
return new JAXBElement(new QName("someField"), SomeParentType.SomeField.class, someField);
}
}
Demo Code
Below is some demo code to exercise your use case:
import javax.xml.bind.*;
import java.math.BigInteger;
public class Demo {
public static void main(String[] args) throws Exception {
// Create the JAXBContext to bring in the Registry
JAXBContext jc = JAXBContext.newInstance(SomeParentType.class, Registry.class);
// Create the instance of SomeField
SomeParentType.SomeField sf = new SomeParentType.SomeField();
sf.order = new BigInteger("1");
// Wrap the SomeField in a JAXBElement & specify the nil aspect
Registry registry = new Registry();
JAXBElement<SomeParentType.SomeField> jaxbElement = registry.createSomeField(sf);
jaxbElement.setNil(true);
SomeParentType spt = new SomeParentType();
spt.someField = jaxbElement;
// Marshal the domain model to XML
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(spt, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<someParentType>
<someField xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" order="1" xsi:nil="true"/>
</someParentType>

Moxy - Creating XML element with no corresponding Java Property

I've been using Moxy to successfully marshall / unmarshall complex xml types into a more simple java Structure. In particular, I'm working with ISO Pain 20022 messages and there are a number of fields that are present in the XML that we don't care about:
<?xml version="1.0" encoding="UTF-8"?>
<iso:Document xmlns:iso="urn:iso:std:iso:20022:tech:xsd:pain.001.001.04" >
<iso:CstmrCdtTrfInitn>
<iso:GrpHdr>
<iso:MsgId>OriginalMessageID</iso:MsgId>
<iso:CreDtTm>2013-05-29T20:02:22.615</iso:CreDtTm>
<iso:NbOfTxs>1</iso:NbOfTxs>
<iso:InitgPty/>
</iso:GrpHdr>
<iso:PmtInf>
...
</iso:Document>
Here is my oxm bindings file piece:
<xml-element java-attribute="messageId" xml-path="iso:CstmrCdtTrfInitn/iso:GrpHdr/iso:MsgId/text()"/>
<xml-element java-attribute="creationDateTime" xml-path="iso:CstmrCdtTrfInitn/iso:GrpHdr/iso:CreDtTm/text()"/>
I need to generate the additional two xml elements iso:NbOfTxs and iso:InitgPty which will always be the same and there is no corresponding property for these on the java class that is generating the xml.
Is this possible?
Thanks.
I am still working on this use case. Below is the XML I am currently able to generate (I recognize that it's not correct).
Output
<?xml version="1.0" encoding="UTF-8"?>
<iso:Document xmlns:iso="urn:iso:std:iso:20022:tech:xsd:pain.001.001.04">
<iso:CstmrCdtTrfInitn>
<iso:GrpHdr>
<iso:MsgId>OriginalMessageID</iso:MsgId>
</iso:GrpHdr>
</iso:CstmrCdtTrfInitn>
<iso:CstmrCdtTrfInitn>
<iso:GrpHdr>
<iso:CreDtTm>2013-05-29T20:02:22.615</iso:CreDtTm>
<iso:NbOfTxs>1</iso:NbOfTxs>
<iso:InitgPty/>
</iso:GrpHdr>
</iso:CstmrCdtTrfInitn>
</iso:Document>
Document
Below is a simplified version of your domain model:
import java.util.Date;
public class Document {
private String messageId;
private Date creationDateTime;
}
oxm.xml
In the metadata below I'm trying to use an XmlAdapter to convert the Date property into a more complex object that can write out the other 2 XML elements.
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="forum16839007">
<xml-schema
namespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.04"
element-form-default="QUALIFIED">
<xml-ns prefix="iso" namespace-uri="urn:iso:std:iso:20022:tech:xsd:pain.001.001.04"/>
</xml-schema>
<java-types>
<java-type name="Document" xml-accessor-type="FIELD">
<xml-root-element name="Document"/>
<java-attributes>
<xml-element java-attribute="messageId" xml-path="iso:CstmrCdtTrfInitn/iso:GrpHdr/iso:MsgId/text()"/>
<xml-element java-attribute="creationDateTime" xml-path=".">
<xml-java-type-adapter value="forum16839007.ExtraAdapter"/>
</xml-element>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
ExtraAdapter
Here is the XmlAdapter that converts a Date into a more complex object.
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
public class ExtraAdapter extends XmlAdapter<ExtraAdapter.Extra, Date>{
public static class Extra {
#XmlPath("iso:CstmrCdtTrfInitn/iso:GrpHdr/iso:CreDtTm/text()")
public Date creationDateTime;
#XmlPath("iso:CstmrCdtTrfInitn/iso:GrpHdr/iso:NbOfTxs/text()")
public final int NbOfTxs = 1;
#XmlPath("iso:CstmrCdtTrfInitn/iso:GrpHdr/iso:InitgPty/text()")
public final Empty initgPty = new Empty();
}
public static class Empty {
}
#Override
public Date unmarshal(Extra extra) throws Exception {
return extra.creationDateTime;
}
#Override
public Extra marshal(Date date) throws Exception {
Extra extra = new Extra();
extra.creationDateTime = date;
return extra;
}
}
Demo
import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "forum16839007/oxm.xml");
JAXBContext jc = JAXBContext.newInstance(new Class[] {Document.class}, properties);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum16839007/input.xml");
Document document = (Document) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(document, System.out);
}
}

How to inject dependencies into resources with Jersey?

I'm having the following code:
#Path("stores")
class StoreResources {
private ServerConfig config;
#GET
public String getAll() {
//do some stuff with ServerConfig
}
}
And I need the ServerConfig object to be injected into this class from outside and use it inside the getAll() method.
What are the possible ways to achieve it? Should I use a DI framework like Guice or Spring?
This is a good blog about Spring injection under Jersey http://javaswamy.blogspot.com/2010/01/making-jersey-work-with-spring.html
The upshot is you use annotations to flag fields that are to be injected, an example resource being
package com.km.services;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.sun.jersey.spi.inject.Inject;
import com.km.spring.SimpleBean;
#Path("/hello")
#Component
#Scope("request")
public class HelloResource {
#Inject private SimpleBean simpleBean;
#GET
#Produces("text/plain")
public String getMessage() {
return simpleBean.sayHello();
}
}
For my purposes the configuration was excessively difficult so I used a static spring resolver factory to resolve the bean. eg.
private SimpleBean simpleBean = SpringBeanFactory.getBean("mySimpleBean");
You don't need Spring or Guice to inject a ServletConfig. Jersey does through its own injection mechanism. Refer to the simple-servlet example that comes with Jersey samples distribution. Here is the sample code that injects a HttpServletRequest and a ServletConfig onto a resource:
#Path("/resource1")
public class ResourceBean1 {
#Context
HttpServletRequest servletRequest;
#Context
ServletConfig servletConfig;
#GET
#Produces("text/plain")
public String describe() {
return "Hello World from resource 1 in servlet: '" +
servletConfig.getServletName() +
"', path: '" +
servletRequest.getServletPath() +
"'";
}
}
When deploying an JAX-RS application using Servlet then ServletConfig, ServletContext, HttpServletRequest and HttpServletResponse are available for injection using #Context.