I'm calling this method and getting a 500 back from it.
In the debugger I'm able to step though it all the way to the return statement at the end. No problem, r is populated as expected after Response.build() is called, the status says 200 OK. But that's not what ends up getting produced. I've even told eclipse to break on any Exception.
#GET
#Path("/getAllAppMessagesAsXML")
#Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML})
public Response getAllAppMessagesXML(#QueryParam("applicationId") String applicationId){
ResponseList list = new ResponseList();
ArrayList<XmlMessageBean> xmlmessages = new ArrayList<>();
try {
List<AppMessage> messages = //Gets from a database
for(AppMessage m : messages){
XmlMessageBean xm = new XmlMessageBean();
xm.setId(m.getId());
xm.setApplicationId(m.getApplicationId());
xm.setMessageBody(m.getMessageBody());
xm.setMessageLevel(m.getMessageLevel());
xm.setMessageTitle(m.getMessageTitle());
xmlmessages.add(xm);
}
} catch (Exception e) {
logger.error("ERROR Failed to save Message AppMessageService.saveAppMessage()", e);
Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
list.setList(xmlmessages);
Response r = null;
try{
r = Response.status(Response.Status.OK).entity(list).build();
}catch(Exception e){
e.printStackTrace();
}
return r;
}
XmlMessageBean.java
#XmlRootElement(name="AppMessage")
#XmlAccessorType(XmlAccessType.FIELD)
public class XmlMessageBean {
#XmlElement
private Long id;
#XmlElement
private String applicationId;
#XmlElement
private String messageTitle;
#XmlElement
private String messageBody;
#XmlElement
private String messageLevel;
public XmlMessageBean(){
}
//getters and setters
}
ResponseList.java
#XmlRootElement(name = "ResponseList")
public class ResponseList {
public ResponseList(){
}
#XmlElement(name="list")
private List<XmlMessageBean> list;
public List<XmlMessageBean> getList() {
return list;
}
public void setList(List<XmlMessageBean> list) {
this.list = list;
}
}
I've got this all running in a jersey.servlet.ServletContainer
I'm stumped. I can't figure out how to get it to produce any kind of error message other than a generic 500. I've tried setting up an exception mapper as some other posts have mentioned but this also isn't picking anything up.
IllegalAnnotationException: Class has two properties of the same name "list"
Look at your two model classes XmlMessageBean and ResponseList. Do you see any difference? The main difference (and the cause for the error), is the #XmlAccessorType(XmlAccessType.FIELD) annotation (or lack there of). JAXB by default will look for the public properties (JavaBean getters/setters). So that's one property. But then you define another property by using the #XmlElement annotation on the field. The reason it works for XmlMessageBean is that it overrides the default public property lookup by changing it to XmlAccessType.FIELD
So you can simply annotate the ResponseList with #XmlAccessorType(XmlAccessType.FIELD) and it should work. You could also simply get rid of all the #XmlElement annotations, and get rid of #XmlAccessorType(XmlAccessType.FIELD), and it will still work, as it will look up the JavaBean properties. Generally, for me I only use the #XmlElement annotations when I need to change the name of the property, and just put it on the getter, for example.
private String messageBody;
#XmlElement(name = "body")
public String getMessageBody(){
return messageBody;l
}
Other than that, I normally leave out the annotation, and also the #XmlAccessorType annotation, and just let it resolve to the default behavior.
Related
I have a DTO class which has a property like:
#JsonIgnoreProperties(ignoreUnknown = true)
public class WPPostResponse {
#JsonProperty("featuredMedia")
Long featured_media;
public Long getFeatured_media() {
return featured_media;
}
public void setFeatured_media(Long featured_media) {
this.featured_media = featured_media;
}
}
The input JSON has the key featured_media. I convert the JSON string to the object and then sends it to the client response as JSON. I want the final response JSON to have featuredMedia as the key. I am however getting null as the value. If I remove the JsonProperty, it gives the value, but the key is having underscore. How to fix this? Thanks.
Always respect the Java naming conventions in your Java code. Use annotations to deal with Json not respecting them.
In this case, use JsonAlias
Annotation that can be used to define one or more alternative names for a property, accepted during deserialization as alternative to the official name
public class WPPostResponse {
#JsonAlias("featured_media")
Long featuredMedia;
public Long getFeaturedMedia() {
return featuredMedia;
}
public void setFeaturedMedia(Long featuredMedia) {
this.featuredMedia = featuredMedia;
}
}
You can use the JsonProperty on setters and getters to have different namings during serialization and deserialization
#JsonIgnoreProperties(ignoreUnknown = true)
public class WPPostResponse {
Long featuredMedia;
#JsonProperty("featuredMedia") // output will be featuredMedia
public Long getFeatured_media() {
return featuredMedia;
}
#JsonProperty("featured_media") // input should be featured_media
public void setFeatured_media(Long featured_media) {
this.featuredMedia = featured_media;
}
}
And also you set access level to #JsonProperty annotation
#JsonProperty(value = "featured_media", access = JsonProperty.Access.WRITE_ONLY)
The error show up when My code like this:
#Test
public void getTemplateByIdTest() throws Exception {
client.get().uri("/template/getTemplate/7")
.exchange()
.expectStatus().isOk()
.expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
.expectBody(VtTemplateVO.class)
.returnResult();
}
When I change my code like this,it's ok!
#Test
public void getTemplateByIdTest() throws Exception {
client.get().uri("/template/getTemplate/7")
.exchange()
.expectStatus().isOk()
.expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
.expectBody(String.class)
.returnResult();
}
Why when I use .expectBody(VtTemplateVO.class) it will say org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/json;charset=UTF-8' not supported
Somebody knows? please help,thanks
I was also facing this issue caused by Jackson.There needs to be a default constructor for the VtTemplateVO.class with annotated properties. Ex. what I did-
#JsonCreator
public Comment(#JsonProperty("id")String id, #JsonProperty("text")String text, #JsonProperty("createdTime") LocalDate createdTime) {
this.id = id;
this.text = text;
this.createdTime = createdTime;
}
Hope it works for you as well. :)
Apparently, any problem in creating and populating the object might result in this error.
In my case, I had duplicated #JsonProperty, example:
public class MyObject {
#JsonProperty("foo")
private String foo;
#JsonProperty("foo")
private String bar;
}
So I fixed to:
public class MyObject {
#JsonProperty("foo")
private String foo;
#JsonProperty("bar")
private String bar;
}
And it worked.
But I've seen other people commenting that other mistakes might result in this error, like:
Not having setter methods
Having overloaded setters
Not having a default constructor
Instead of annotating every parameter with #JsonProperty, you can also compile your code with the -parameters flag (since Java 8). This will retain the parameter names in the bytecode thus allowing Jackson to use them. See the Maven docs
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
You should also consider this https://stackoverflow.com/a/44075684/2145769 that now parameter names become part of your API.
For me, the issue was caused by duplicated #Jsonproperty values, as Jefferson Lima pointed in his answer. I can't see your VtTemplateVO POJO class in your question but it might cause the problem.
In my case, I tried to unpack several nested values from "game" JSON node in my POJO class to get the desired mapping schema when this exception occurred.
"game": {
"home_team_id": 2
"visitor_team_id": 5
}
The following approach didn't work.
public class MyPojo {
#JsonProperty("game")
public void unpackHomeTeamId(Map<String, String> game) {
homeTeamId = game.get("home_team_id");
}
#JsonProperty("game")
public void unpackAwayTeamId(Map<String, String> game) {
awayTeamId = game.get("visitor_team_id");
}
}
The solution was setting all fields in one method thus avoiding confusing Jackson mapper. It also led me to a more concise design.
#JsonProperty("game")
public void unpackNestedGameProperties(Map<String, String> game) {
homeTeamId = game.get("home_team_id");
awayTeamId = game.get("visitor_team_id");
}
Use
.accept(MediaType.APPLICATION_JSON)
as
webClientBuilder.build()
.post()
.uri(ccpApiUrl)
//.accept(MediaType.APPLICATION_JSON)
.bodyValue(customerRequest)
.exchange()
.doOnSuccess(
clientResponse -> logger.info("clientResponse.headers() = " + clientResponse.headers())
)
.doOnSuccess(
clientResponse -> {
logger.info("clientResponse.statusCode() = " + clientResponse.statusCode());
getStatus(clientResponse.statusCode());
})
//.timeout(Duration.ofSeconds(5))
.flatMap(clientResponse -> clientResponse.bodyToMono(CcpResponse.class))
// .retryWhen(fixedRetry)
.block();
As the title says....
I want to build a POJO with four field variables and at certain runtime events create an instance of this POJO with access to possibly maybe two or three of the fields.
public class Category implements Serializable {
private String name;
private String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Lets say I create a new Category object but I only want to be able to have access to the name field during runtime. Is there a design pattern I can use to achieve this? I thought about the strategy pattern and looked at the builder but I am still confused if I can do this in java.
Basically the overall goal is to grab an object from a database and return it as a JSON response in jax rs. But sometimes I dont want a complete object returned but only lets say halve of the object to be accessible at during certain runtime events. My apologies if this seems like a dumb question but I know what I want to do but just don't know the best way.
I have the same problem with you, and my project was used springmvc,and the json tool is jackson.With the problem solved, I just use #JsonIgnore.For more details,just read jackson-how-to-prevent-field-serialization
So someone correct me if I am wrong or see a better option than this...with alot of objects this can be alot of extra code for serialization and deserialization...Jackson Provisions is what I need. I can use the annotation #JsonView(DummyClass.class) on the field variable. I will accept this a the best answer in a day or two unless someone else posts a better response.
// View definitions:
class Views {
static class Public { }
static class ExtendedPublic extends PublicView { }
static class Internal extends ExtendedPublicView { }
}
public class Bean {
// Name is public
#JsonView(Views.Public.class) String name;
// Address semi-public
#JsonView(Views.ExtendPublic.class) Address address;
// SSN only for internal usage
#JsonView(Views.Internal.class) SocialSecNumber ssn;
}
With such view definitions, serialization would be done like so:
// short-cut:
objectMapper.writeValueUsingView(out, beanInstance, ViewsPublic.class);
// or fully exploded:
objectMapper.getSerializationConfig().setSerializationView(Views.Public.class);
// (note: can also pre-construct config object with 'mapper.copySerializationConfig'; reuse)
objectMapper.writeValue(out, beanInstance); // will use active view set via Config
// or, starting with 1.5, more convenient (ObjectWriter is reusable too)
objectMapper.viewWriter(ViewsPublic.class).writeValue(out, beanInstance);
This information was pulled from http://wiki.fasterxml.com/JacksonJsonViews
with jackson 2.3, I can do this with JAX-RS
public class Resource {
#JsonView(Views.Public.class)
#GET
#Produces(MediaType.APPLICATION_JSON )
public List<Object> getElements() {
...
return someResultList;
}
}
probably a stupid question, but I'm stuck.
I try do parse a huge xml document retrieved from a REST service.
What I'm interested in are both the abstract parts.
<article article-type="research-article">
<front>
<article-meta>
<abstract></abstract>
<abstract abstract-type="summary"></abstract>
</article-meta>
</front>
</article>
In my front class, I do the following:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement
public class Front {
#XmlElementWrapper(name = "article-meta")
#XmlElement(name="abstract")
private List<AuthorSummary> authorSummaries = new ArrayList<AuthorSummary>();
/** Getter and Setter **/
}
Sadly, I only the get the first abstract, but there the content as well. You can see my AuthorSummary Class below.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement
public class AuthorSummary {
#XmlElement(name = "title")
private String title;
#XmlElement(name = "p")
private String content;
#XmlAttribute(name = "abstract-type")
private String abstractType;
/** Getter and Setter **/
}
So, I'm stuck and would be very glad for any hints.
Thank you very much
I have a solution, but it is not using jaxb or even data binding at all. So if you are stuck to data binding I will delete my answer. Otherwise, I like you point to data projection (Disclosure: I am affiliated with that project) instead of data binding:
public class ReadElementsWithSameName {
public interface Article {
#XBRead("./#article-type")
String getType();
#XBRead("./front/article-meta/abstract")
List<String> getAllAbstracts();
#XBRead("./front/article-meta/abstract[#abstract-type='summary']")
String getSummary();
}
// Configure the underlying document builder to not load the (nonexisting) DTD
private static final XMLFactoriesConfig nonValidatingConfig = new DefaultXMLFactoriesConfig() {
#Override
public DocumentBuilderFactory createDocumentBuilderFactory() {
DocumentBuilderFactory factory = super.createDocumentBuilderFactory();
try {
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
}
return factory;
}
};
public static void main(String... args) throws IOException {
List<Article> articles = new XBProjector(nonValidatingConfig).io().url("res://data.xml").evalXPath("/article").asListOf(Article.class);
for (Article article:articles) {
System.out.println(article.getType());
System.out.println(article.getSummary());
System.out.println(article.getAllAbstracts());
}
}
}
Instead of reflecting the XML structure with java classes, just define the Java API as a "projection interface" with the accessors (and setters) you like to have. Afterwards, let the projection framework take care of reading and writing your changes to the DOM.
I want convert json string to one object.
The json looks like this:
{"receive":1413342268310}
And the object is like:
public class PositionBean {
private Long id;
private Date receive;
public void setReceive (Date receive) {
this.receive = receive;
}
public void setReceive (Long receive) {
this.receive = new Date (receive);
}
public Long getReceive () {
return receive.getTime ();
}
}
All the set and get methods I have to use in other class, so I can't delete one method.
When I invoke
objectMapper.readValue(str, PositionBean.class);
It prompt exception, the jackon don't know which method set, so I use #JsonIgnore, but I found the receive is null.
You can use annotation #JsonSetter to specify which method should be used as setter.
Example:
public class PositionBean {
private Long id;
private Date receive;
public void setReceive (Date receive) {
this.receive = receive;
}
#JsonSetter
public void setReceive (Long receive) {
this.receive = new Date (receive);
}
public Long getReceive () {
return receive.getTime ();
}
}
When you mark setter (e.g. setXXX) with #JsonIgnore it means that property XXX will be ignored.
From documentation:
For example, a "getter" method that would otherwise denote a property
(like, say, "getValue" to suggest property "value") to serialize,
would be ignored and no such property would be output unless another
annotation defines alternative method to use.
You can also use
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
This will not throw any mapping exception even if u dont have an appropriate field in the mapping class corresponding to a JSON field. Once configured u can use ur code for further processing.
objectMapper.readValue (str, PositionBean.class);