I am trying to receive this object in my web service from a html page. In the browser opened by eclipse works fine but when i try the same thing in firefox i get the fallowing problem:
Caused by: javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.w3.org/1999/xhtml", local:"userclient"). Expected elements are <{}userclient>
#XmlRootElement
public class Userclient {
#XmlElement
private String first_name;
#XmlElement
private String last_name;
#XmlElement
private String email;
public Userclient() {
}
//....
}
//Reciving
#PUT
#Consumes("application/xml")
public Response addUser(Userclient user,
#CookieParam("sessionId") String sessionCookie) {
}
//Sending
<script>
RestServlet.addUser({
$entity : userclient
});
</script>
Here are a couple of options for solving your problem based on what your XML looks like:
Option #1 - elementFormDefault="unqualified"
Input XML
If in your XML only the global (top level) elements are namespace qualified:
<ns:userclient xmlns:ns="http://www.w3.org/1999/xhtml">
<first_name>Jane</first_name>
<ns:userclient>
Userclient.java
Then you could just specify the namespace parameter on the #XmlRootElement annotation.
#XmlRootElement(namespace="http://www.w3.org/1999/xhtml"
public class Userclient {
Option #2 - elementFormDefault="qualified"
Input XML
If all the elements are namespace qualified like:
<userclient xmlns="http://www.w3.org/1999/xhtml">
<first_name>Jane</first_name>
<userclient>
package-info.java
You can use the package level #XmlSchema annotation to apply namespace qualification to your model.
#XmlSchema(
namespace = "http://www.w3.org/1999/xhtml",
elementFormDefault = XmlNsForm.QUALIFIED)
package example;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
For More Information
Below is a link to an article on my blog that covers more about JAXB and namespace qualification:
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
Note
You are currently adding more annotations than are necessary. JAXB is configuration by exception so you only need to add annotations where you want the XML representation to differ from the default.
For More Information
Below is a link to an article on my blog that covers more about JAXB's default XML representation:
http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Userclient {
private String first_name;
private String last_name;
private String email;
public Userclient() {
}
//....
}
Related
I must run project with JEE and EclipseLink 2.6.1. Maven successfully compiles the project, but when I put . jar on Payara and try to run it it gets problems of the type:
The abstract schema type 'NetServer'; is unknown.
The state field path 'netserver.active'; cannot be resolved to a valid type.
The problem occurs in queries with all entities with annotations #DiscriminatorValue. Entity looks like this:
Main class (Servers) :
#Entity
#Table("Servers")
#DiscriminatorColumn(
name = "SERVER_TYPE",
discriminatorType = DiscriminatorType.STRING
)
#DiscriminatorValue("servers")
public class Servers{
#Id
private Long id;
private String name;
private String hostname;
private Boolean active;
//getters& setters
}
Netserver:
#Entity
#DiscriminatorValue("netserver")
public class NetServer extends Server{
private String url;
public Netserver();
public Netserver(Server server){super(server);}
//getters&setters
}
And I wonder what the problem is that he throws away exceptions?
I am using Spring Data MongodB 1.4.2.Release version. For Spring Data MongoDB, I have created the custom repository interface and implementation in one location and create custom query function getUsersName(Users users).
However I am still getting below exception:
Caused by: org.springframework.data.mapping.PropertyReferenceException:
No property get found for type Users! at org.springframework.data.mapping.PropertyPath. (PropertyPath.java:75) at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327) at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:359) at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:359) at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307) at
org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270) at
org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:241) at
org.springframework.data.repository.query.parser.Part.(Part.java:76) at
org.springframework.data.repository.query.parser.PartTree$OrPart.(PartTree.java:201) at
org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:291) at
org.springframework.data.repository.query.parser.PartTree$Predicate.(PartTree.java:271) at
org.springframework.data.repository.query.parser.PartTree.(PartTree.java:80) at
org.springframework.data.mongodb.repository.query.PartTreeMongoQuery.(PartTreeMongoQuery.java:47)
Below is my Spring Data MongoDB structure:
/* Users Domain Object */
#Document(collection = "users")
public class Users {
#Id
private ObjectId id;
#Field ("last_name")
private String last_name;
#Field ("first_name")
private String first_name;
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
}
/* UsersRepository.java main interface */
#Repository
public interface UsersRepository extends MongoRepository<Users,String>, UsersRepositoryCustom {
List findUsersById(String id);
}
/* UsersRepositoryCustom.java custom interface */
#Repository
public interface UsersRepositoryCustom {
List<Users> getUsersName(Users users);
}
/* UsersRepositoryImpl.java custom interface implementation */
#Component
public class UsersRepositoryImpl implements UsersRepositoryCustom {
#Autowired
MongoOperations mongoOperations;
#Override
public List<Users> getUsersName(Users users) {
return mongoOperations.find(
Query.query(Criteria.where("first_name").is(users.getFirst_name()).and("last_name").is(users.getLast_name())), Users.class);
}
/* Mongo Test function inside Spring JUnit Test class calling custom function with main UsersRepository interface */
#Autowired
private UsersRepository usersRepository;
#Test
public void getUsersName() {
Users users = new Users();
users.setFirst_name("James");`enter code here`
users.setLast_name("Oliver");
List<Users> usersDetails = usersRepository.getUsersName(users);
System.out.println("users List" + usersDetails.size());
Assert.assertTrue(usersDetails.size() > 0);
}
The query method declaration in your repository interface is invalid. As clearly stated in the reference documentation, query methods need to start with get…By, read_By, find…By or query…by.
With custom repositories, there shouldn't be a need for method naming conventions as Oliver stated. I have mine working with a method named updateMessageCount
Having said that, I can't see the problem with the code provided here.
I resolved this issue with the help of this post here, where I wasn't naming my Impl class correctly :
No property found for type error when try to create custom repository with Spring Data JPA
I'm working on a RestWebService using Resteasy. The basic implementation works fine. Know I tried to return a Complexer- Object through rest...
Actually its pretty easy..I thought. I'm getting a problem because of my nested object (Address)...
What I try is this:
#XmlRootElement(name = "person")
#XmlAccessorType(XmlAccessType.FIELD)
public class Person implements Serializable {
private static final long serialVersionUID = 1199647317278849602L;
private String uri;
private String vName;
private String nName;
private Address address;
.....
#XmlElementWrapper(name="Former-User-Ids")
#XmlElement(name="Adress")
public Address getAddress() {
return address;
}
....
Address looks like this:
#XmlRootElement(name = "address")
#XmlAccessorType(XmlAccessType.FIELD)
public class Address {
private String uri;
private String street;
private String city;
public String getCity() {
return city;
}
public String getStreet() {
return street;
}
....
The Restservice looks like this. It worked perfect without the address object..
#Path("/getPersonXML/{personNumber}")
#GET
#Produces(MediaType.APPLICATION_XML)
public Patient getPatientXML(#PathParam("personNumber") String personNumber) throws ParseException {
Address a1 = new Address("de.person/address/" + "432432","Teststret12","TestCity", "32433", "TestCountry", "081511833");
Patient p1 = new Person();
p1.setAddress(a1);
p1.setUri("de.spironto/person/"+ "432432");
p1.setnName("Power");
p1.setvName("Max");
return p1;
}
At the moment I'm always getting a
javax.xml.bind.JAXBException:
Any Ideas?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
PROBLEM
The #XmlElementWrapper annotation must be used with a collection property. This means you can have:
#XmlElementWrapper
public List<PhoneNumber> getPhoneNumbers() {
return phoneNumbers;
}
But not
#XmlElementWrapper
public Address getAddress() {
return address;
}
SOLUTION #1 - Using Any JAXB Proivder
You could use an XmlAdapter to accomplish this (see linked answer below):
Access attribute of internal element in the most simple way
SOLUTION #2 - Using EclipseLink JAXB (MOXy)
You could leverage the #XmlPath extension to map this use case:
#XmlPath("Former-User-Ids/Address")
public Address getAddress() {
return address;
}
For More Information
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
After building a small marshaller test. I got the failure that there are several properties with the same name. So I tried to delete all #XML_Eleemets annotations in the Address class.
That worked for me...
My setup:
JBoss AS 7.1.1 using JPA, Hibernate (to connect to PostgreSQL), RESTEasy, Jackson 1.9.2 for JSON, EclipseLink MOXy 2.4.1 for XML
I have two entities - Group and User. A group contains many users (one-to-many). I'm declaring a bi-directional relationship with JPA annotations (see below), so I have to prevent cycles by using #JsonManagedReference/#JsonBackReference (for JSON) and #XmlInverseReference (for XML). This works as expected, except when I try to create a user via REST, I can't assign her to a group when using XML. When using JSON, it works:
Jackson JSON works (successfully adds Jane Doe and places her in group 5):
POST request to /user
Content-Type: application/json
Accept: application/json
Body: {"name":"Jane Doe", "group":{"id":5}}
Response:
{
"id": 12,
"name":"Jane Doe"
}
Hibernate: insert into users (group_id, name, id) values (5, 'Jane Doe', 12)
Here's the GroupEndpoint response after adding a user with Jackson:
GET request to /group
Accept: application/json
Response:
[{"id":5,"name":"My User Group","users":[{"id":12,"name":"Jane Doe"}]}
MOXy XML doesn't work (Jane Doe is orphaned):
POST request to /user
Content-Type: application/xml
Accept: application/xml
Body: <name>Jane Doe</name><group><id>5</id></group>
Response:
<user><name>Jane Doe</name><id>12</id></user>
Hibernate: insert into users (group_id, name, id) values (null, 'Jane Doe', 12)
Here's the GroupEndpoint response after adding a user with MOXy:
GET request to /group
Accept: application/xml
Response:
<collection>
<group><id>5</id><name>My User Group</name></group>
</collection>
I've tried #XmlID and #XmlIDREF, same issue. #XmlTransient will similarly ignore the child-to-parent relationship on both marshal and unmarshal.
My question:
How can I add a User to a Group via the User REST endpoint without MOXy ignoring the new user's group field (marked as #XmlInverseReference)?
Should I augment my REST endpoints, create an XmlAdapter, or write a custom serializer? Am I missing an easy solution with different annotations? Is there an entirely different approach to exposing relational objects via REST that is preferred? Any help is much appreciated.
Here's the group entity:
#Entity
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Group implements Serializable {
#Id
private Long id;
#Column
private String name;
#OneToMany(mappedBy="group", cascade=CascadeType.ALL)
#JsonManagedReference("group-user")
private Set<User> users;
// Omitting getters and setters etc...
}
Here's the user entity:
#Entity
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class User implements Serializable {
#Id
private Long id;
#Column
private String name;
#ManyToOne
#JsonBackReference("group-user")
#XmlInverseReference(mappedBy="users")
private Group group;
// Omitting getters and setters etc...
}
Here's the User REST endpoint:
#Stateful
#Path("/user")
#TransactionAttribute
public class UserEndpoint {
#PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager em;
#POST
#Consumes({"application/xml","application/json"})
public User create(User entity) {
em.joinTransaction();
em.persist(entity);
return entity;
}
}
Here's the Group REST endpoint (included to show the need to prevent cycles):
#Stateful
#Path("/group")
#TransactionAttribute
public class GroupEndpoint {
#PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager em;
#GET
#Produces({"application/xml","application/json"})
public List<Group> listAll() {
final List<Group> results = em.createQuery("SELECT x FROM Group x").getResultList();
return results;
}
}
Here's the GroupEndpoint MOXy response after adding a user with Jackson, to test for cycles:
GET request to /group
Accept: application/xml
Response:
<collection>
<group>
<id>5</id>
<name>My User Group</name>
<users><id>12</id><name>Jane Doe</name></users>
</group>
</collection>
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
Support for your use case has now been implemented in EclipseLink 2.5.0. You can download a nightly label (staring March 1st, 2013) from the following link.
http://www.eclipse.org/eclipselink/downloads/nightly.php
JAVA MODEL
Now MOXy supports specifying the #XmlInverseReference annotation on both directions of a relationship. When specified alone it is treated just like #XmlTransient is for marshalling, and to make it writeable you need to use it in combination with #XmlElement.
User
import java.io.Serializable;
import javax.persistence.*;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlInverseReference;
#Entity
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class User implements Serializable {
#Id
private Long id;
#Column
private String name;
#ManyToOne
//#JsonBackReference("group-user")
#XmlElement
#XmlInverseReference(mappedBy="users")
private Group group;
public Group getGroup() {
return group;
}
// Omitting other getters and setters etc...
}
Group
import java.io.Serializable;
import java.util.Set;
import javax.persistence.*;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlInverseReference;
#Entity
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Group implements Serializable {
#Id
private Long id;
#Column
private String name;
#OneToMany(mappedBy="group", cascade=CascadeType.ALL)
//#JsonManagedReference("group-user")
#XmlElement
#XmlInverseReference(mappedBy="group")
private Set<User> users;
public Set<User> getUsers() {
return users;
}
// Omitting other getters and setters etc...
}
DEMO CODE
Demo
Below is some code that can be run to prove that everything works. In addition to the XML use case, MOXy could also be used to handle the JSON.
import java.io.StringReader;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(User.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
// XML USE CASE
StringReader xml = new StringReader("<user><name>Jane Doe</name><group><id>5</id></group></user>");
User userFromXML = (User) unmarshaller.unmarshal(xml);
System.out.println(userFromXML.getGroup().getUsers());
// JSON USE CASE
StringReader json = new StringReader("{\"name\":\"Jane Doe\", \"group\":{\"id\":5}}");
unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
StreamSource jsonSource = new StreamSource(json);
User userFromJSON = unmarshaller.unmarshal(jsonSource, User.class).getValue();
System.out.println(userFromJSON.getGroup().getUsers());
}
}
Output
Below is the output from running the demo code showing that the back pointers have been set correctly.
[forum14844691.User#147ee929]
[forum14844691.User#685c53ff]
FOR MORE INFORMATION
http://blog.bdoughan.com/2013/03/moxys-xmlinversereference-is-now-truly.html
http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
I have a RESTful service that needs to return only a few of the XmlElements if "selectors" are submitted with the request. The URL will take the form of:
/merchants/{merchantId}/profile?selectors=<field1|field2|....|fieldN>
The selectors are optional, and so far I have implemented the service for the full set of elements to be returned for {merchantId} without selectors specified. Now I'm trying to figure out how to add in this added functionality. I'm sure this is covered in documentation but I can't find where. Any RTFM pointers would be appreciated. Thanks.
EclipseLink JAXB (MOXy) does not currently offer a mechanism to selectively indicate which fields/properties are included on a per marshal operation. This sounds like an interesting use case. I would appreciate if you could enter this as an enhancement request using the following link:
https://bugs.eclipse.org/bugs/enter_bug.cgi?product=EclipseLink
Below is an example of how you could use a stateful XmlAdapter to implement this use case by exploiting the fact that a JAXB (JSR-222) will not marshal an element when the value is null (see: http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html).
FieldAdapter
Since we are going to leverage stateful XmlAdapters we're going to need one per field. Since all our XmlAdapters will perform the same logic we can create a super class that the others can extend from.
package forum13094195;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class FieldAdapter<T> extends XmlAdapter<T, T> {
private boolean include;
public FieldAdapter() {
this.include = true;
}
public FieldAdapter(boolean include) {
this.include = include;
}
#Override
public T marshal(T value) throws Exception {
if(include) {
return value;
}
return null;
}
#Override
public T unmarshal(T value) throws Exception {
return value;
}
}
Field1Adapter
package forum13094195;
public class Field1Adapter extends FieldAdapter<String> {
public Field1Adapter() {}
public Field1Adapter(boolean include) {
super(include);
}
}
Field2Adapter
package forum13094195;
public class Field2Adapter extends FieldAdapter<Integer>{
public Field2Adapter() {}
public Field2Adapter(boolean include) {
super(include);
}
}
Field3Adapter
package forum13094195;
public class Field3Adapter extends FieldAdapter<String> {
public Field3Adapter() {}
public Field3Adapter(boolean include) {
super(include);
}
}
Merchant
The #XmlJavaTypeAdapter annotation is used to specify an XmlAdapter on a field/property.
package forum13094195;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Merchant {
#XmlJavaTypeAdapter(Field1Adapter.class)
String field1;
#XmlJavaTypeAdapter(Field2Adapter.class)
int field2;
#XmlJavaTypeAdapter(Field3Adapter.class)
String field3;
}
Demo
The demo code below demonstrates how to set a stateful XmlAdapter on the Marshaller.
package forum13094195;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Merchant.class);
Merchant merchant = new Merchant();
merchant.field1 = "A";
merchant.field2 = 2;
merchant.field3 = "C";
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(merchant, System.out);
marshaller.setAdapter(new Field1Adapter(false));
marshaller.setAdapter(new Field2Adapter(false));
marshaller.setAdapter(new Field3Adapter(true));
marshaller.marshal(merchant, System.out);
}
}
Output
Below is the output from running the demo code. By default the entire object is marshalled out. The second document marshalled does not contain the fields we excluded.
<?xml version="1.0" encoding="UTF-8"?>
<merchant>
<field1>A</field1>
<field2>2</field2>
<field3>C</field3>
</merchant>
<?xml version="1.0" encoding="UTF-8"?>
<merchant>
<field3>C</field3>
</merchant>
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
In EclipseLink 2.5.0 we released a new feature called Object Graphs that enables you to marshal/unmarshal a subset of mapped fields/properties.
// Create the Object Graph
ObjectGraph subset = JAXBHelper.getJAXBContext(jc).createObjectGraph(Merchant.class);
subset.addAttributeNodes("field1", "field1", "fieldN");
// Output XML - Based on Object Graph
marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, subset);
marshaller.marshal(customer, System.out);
For More Information
http://blog.bdoughan.com/2013/03/moxys-object-graphs-partial-models-on.html