jackson AfterburnerModule gives a warning in the log - java

After enabling AfterburnerModule I am seeing the below warning message in the logs. Without AfterburnerModule everything works fine.
Sep 06, 2017 9:11:39 AM com.fasterxml.jackson.module.afterburner.deser.BeanPropertyMutator _reportProblem
WARNING: Disabling Afterburner deserialization for class com.test.Child (field #0; mutator com.test.Child$Access4JacksonDeserializerdc6e0fab), due to access error (type java.lang.IllegalAccessError, message=tried to access method com.test.test2.Parent.setSurname(Ljava/lang/String;)V from class com.test.Child$Access4JacksonDeserializerdc6e0fab)
java.lang.IllegalAccessError: tried to access method com.test.test2.Parent.setSurname(Ljava/lang/String;)V from class com.test.Child$Access4JacksonDeserializerdc6e0fab
at com.test.Child$Access4JacksonDeserializerdc6e0fab.stringSetter(com/test/Child$Access4JacksonDeserializer.java)
at com.fasterxml.jackson.module.afterburner.deser.BeanPropertyMutator.stringSetter(BeanPropertyMutator.java:123)
at com.fasterxml.jackson.module.afterburner.deser.SettableStringMethodProperty.deserializeAndSet(SettableStringMethodProperty.java:60)
at com.fasterxml.jackson.module.afterburner.deser.SuperSonicBeanDeserializer.deserialize(SuperSonicBeanDeserializer.java:156)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3807)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2797)
at com.test.JacksonStuff.main(JacksonStuff.java:19)
My class are as follows:
package com.test.test2;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Parent {
#JsonProperty("surname")
private String surname;
protected Parent() {
}
public Parent(String surname) {
this.surname = surname;
}
public String getSurname() {
return surname;
}
protected void setSurname(String surname) {
this.surname = surname;
}}
package com.test;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.test.test2.Parent;
public class Child extends Parent {
#JsonProperty("name")
private String test;
public Child() {
super();
}
public Child(String var1) {
super(var1);
}
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}}
package com.test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
import java.io.IOException;
public class JacksonStuff {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
AfterburnerModule module = new AfterburnerModule();
mapper.registerModule(module);
String json = "{\"surname\":\"abc\"}";
Child value = mapper.readValue(json, Child.class);
}}
How do I avoid getting this warning in the logs? I cannot modify parent.java as it is from a third party lib and not under my control.

Because void setSurname is protected. Set it to public.

Related

Junit test coverage is showing 0%

I am writing test case for mapper method where new object instance is creating for mapping. How to mock all mapper objects and set in setter? Eclipse tool passing test but jacoco is giving 0% coverage on this code.
public class NewUseInsideMethods {
public StudentOldTestingReturn OldLogicTesting(StudentOldTesting Student) {
StudentOldTestingReturn sturentReturn = new StudentOldTestingReturn();
OldBatchName batchName = new OldBatchName();
batchName.setId("1");
batchName.setName("test");
sturentReturn.setId(batchName.getId());
sturentReturn.setName(Student.getName());
return sturentReturn;
}
}
public class OldBatchName {
private String name;
private String id;
//setter and getter
}
public class StudentOldTesting {
private String name;
private String id;
//setter and getter
}
public class StudentOldTestingReturn {
private String name;
private String id;
//setter and getter
}
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
#ExtendWith(MockitoExtension.class)
class NewUseInsideMethodsTest {
#Test
void OldLogicTesting() throws Exception {
StudentOldTesting oldTesting = new StudentOldTesting();
oldTesting.setName("shraban");
oldTesting.setId("1");
NewUseInsideMethods insideMethods = new NewUseInsideMethods();
StudentOldTestingReturn result = insideMethods.OldLogicTesting(oldTesting);
Assertions.assertNotNull(result);
Assertions.assertEquals("shraban", result.getName());
Assertions.assertEquals("1", result.getId());
}
}

Jackson ObjectMapper setSerializationInclusion() not working

I'm just getting familiar with Jackson binding. However, when I'm testing setSerializationInclusion(JsonInclude.Include.NON_NULL), I found that it's not working sometimes.
Here is my code
package com.blithe.main;
import com.blithe.model.Student;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Jackson_2_NullValue {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Student s = new Student();
String stundetString = mapper.writeValueAsString(s);
System.out.println(stundetString);
// exclude null fields
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
s.setName("ss");
stundetString = mapper.writeValueAsString(s);
System.out.println(stundetString);
}
}
and the POJO
package com.blithe.model;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
// #JsonIgnoreProperties(ignoreUnknown = true)
// exclude null fields for the whole class
// #JsonInclude(Include.NON_NULL)
public class Student {
// exclude the field whe it's empty ("")
// #JsonInclude(value=Include.NON_EMPTY)
private String name;
private Integer age;
private Date birth;
// Jackson ignores it
#JsonIgnore
private String nickName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
}
the output is
{"name":null,"age":null,"birth":null}
{"name":"ss","age":null,"birth":null}
The later one should be null-value excluded, but it doesn't.
However, when I put my code this way.
package com.blithe.main;
import com.blithe.model.Student;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Jackson_2_NullValue {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
Student s = new Student();
String stundetString = mapper.writeValueAsString(s);
System.out.println(stundetString);
// exclude null fields
// mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
s.setName("ss");
stundetString = mapper.writeValueAsString(s);
System.out.println(stundetString);
}
}
It works with the output below
{}
{"name":"ss"}
Is this normal or just some kind of bug? Do I miss anything? The only maven dependency is jackson-databind 2.7.4. Any discussion is welcomed. Thanks!
Do not change ObjectMappers settings while using it. Once mapper has been in use not all settings take effect, because of caching of serializers and deserializers.
Configure an instance once and do not change settings after first use. It is done this way for thread-safety and performance.
Update: Dead links replaced with archive.org ones
http://wiki.fasterxml.com/JacksonFAQThreadSafety
http://wiki.fasterxml.com/JacksonBestPracticesPerformance
So the point is if you are using ObjectMappers at multiple places, try not to create objects again and again. it takes the configs of first initialized.
if you keep changing on a global level it will not work.

Use JsonInclude annotation to ignore empty values in a extended class

Java 1.8, Jackson library 2.1.5
I need to override the behaviour of how an object is serialized in json.
What i need is to ignore the bonus property from the serialized json response in case the value is null and the employee is a Partner employee. However trying the code below does not seem to work as expected.
class Employee{
private String bonus;
public String getBonus(){return bonus;}
public String setBonus(){this.bonus = bonus;}
}
class Partner extends Employee{
#Override
#JsonInclude(NON_NULL)
public String getBonus(){return super.getBonus();}
}
Any help?
If you can get by with excluding all null properties, then you can use the #JsonSerialize on the class. The following test runs successfully for me using Jackson 2.1.5:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.junit.Test;
public class SomeTest {
public static class Employee {
private String bonus;
public String getBonus() {
return bonus;
}
public void setBonus(String bonus) {
this.bonus = bonus;
}
}
#JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public static class Partner extends Employee {
#Override
public String getBonus() {
return super.getBonus();
}
}
#Test
public void testSerialize() throws Exception {
Employee employee = new Employee();
Partner partner = new Partner();
ObjectMapper objectMapper = new ObjectMapper();
System.out.println("Employee: " + objectMapper.writeValueAsString(employee));
System.out.println(" Partner: " + objectMapper.writeValueAsString(partner));
}
}
Output:
Employee: {"bonus":null}
Partner: {}

RDD not serializable Cassandra/Spark connector java API

so I previously had some questions on how to query cassandra using spark in a java maven project here: Querying Data in Cassandra via Spark in a Java Maven Project
Well my question was answered and it worked, however I've run into an issue (possibly an issue). I'm trying to now use the datastax java API. Here is my code:
package com.angel.testspark.test2;
import org.apache.commons.lang3.StringUtils;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import java.io.Serializable;
import static com.datastax.spark.connector.CassandraJavaUtil.*;
public class App
{
// firstly, we define a bean class
public static class Person implements Serializable {
private Integer id;
private String fname;
private String lname;
private String role;
// Remember to declare no-args constructor
public Person() { }
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getfname() { return fname; }
public void setfname(String fname) { this.fname = fname; }
public String getlname() { return lname; }
public void setlname(String lname) { this.lname = lname; }
public String getrole() { return role; }
public void setrole(String role) { this.role = role; }
// other methods, constructors, etc.
}
private transient SparkConf conf;
private App(SparkConf conf) {
this.conf = conf;
}
private void run() {
JavaSparkContext sc = new JavaSparkContext(conf);
createSchema(sc);
sc.stop();
}
private void createSchema(JavaSparkContext sc) {
JavaRDD<String> rdd = javaFunctions(sc).cassandraTable("tester", "empbyrole", Person.class)
.where("role=?", "IT Engineer").map(new Function<Person, String>() {
#Override
public String call(Person person) throws Exception {
return person.toString();
}
});
System.out.println("Data as Person beans: \n" + StringUtils.join("\n", rdd.toArray()));
}
public static void main( String[] args )
{
if (args.length != 2) {
System.err.println("Syntax: com.datastax.spark.demo.JavaDemo <Spark Master URL> <Cassandra contact point>");
System.exit(1);
}
SparkConf conf = new SparkConf();
conf.setAppName("Java API demo");
conf.setMaster(args[0]);
conf.set("spark.cassandra.connection.host", args[1]);
App app = new App(conf);
app.run();
}
}
here is my error:
Exception in thread "main" org.apache.spark.SparkException: Job aborted: Task not serializable: java.io.NotSerializableException: com.angel.testspark.test2.App
at org.apache.spark.scheduler.DAGScheduler$$anonfun$org$apache$spark$scheduler$DAGScheduler$$abortStage$1.apply(DAGScheduler.scala:1020)
at org.apache.spark.scheduler.DAGScheduler$$anonfun$org$apache$spark$scheduler$DAGScheduler$$abortStage$1.apply(DAGScheduler.scala:1018)
at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:47)
at org.apache.spark.scheduler.DAGScheduler.org$apache$spark$scheduler$DAGScheduler$$abortStage(DAGScheduler.scala:1018)
at org.apache.spark.scheduler.DAGScheduler.org$apache$spark$scheduler$DAGScheduler$$submitMissingTasks(DAGScheduler.scala:781)
at org.apache.spark.scheduler.DAGScheduler.org$apache$spark$scheduler$DAGScheduler$$submitStage(DAGScheduler.scala:724)
at org.apache.spark.scheduler.DAGScheduler.processEvent(DAGScheduler.scala:554)
at org.apache.spark.scheduler.DAGScheduler$$anonfun$start$1$$anon$2$$anonfun$receive$1.applyOrElse(DAGScheduler.scala:190)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:498)
at akka.actor.ActorCell.invoke(ActorCell.scala:456)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:237)
at akka.dispatch.Mailbox.run(Mailbox.scala:219)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:386)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Now I KNOW exactly where my error is. It is System.out.println("Data as Person beans: \n" + StringUtils.join("\n", rdd.toArray())); because I need to convert rdd to an Array. However, the API documentation SAID i should be able to do this... this is code copied and pasted from the documentation. Why can I not serialize the RDD to an array?
I've already inserted dummy data into my cassandra using the insertions in my post that I included in the link above.
Also, a previous error that I solved was when i changed all of my getters and setters to lowercase. When I used capitals in them, it produced an error. Why can't I use capitals in my getters and setters here?
Thanks,
Angel
Changing public class App to public class App implements Serializable should fix the error. Because a java inner class will keep a reference to the outer class, your Function object will have a reference to App. As Spark needs to serialize your Function object, it requires App is also serializable.

Simple Java to XML example

I've read a time ago about generate xml from Java using annotations, but I'm not finding a simple example now.
If I want to make a xml file like:
<x:element uid="asdf">value</x:element>
from my java class:
public class Element {
private String uid = "asdf";
private String value = "value";
}
Which annotations should I use to perform that? (I have a xml-schema, if this helps the generation)
--update
The javax.xml.bind.annotation package have the annotations, "but I still haven't found what I'm looking for": an exemple of usage.. :)
Found it:
import java.io.FileOutputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlRootElement;
public class JavaToXMLDemo {
public static void main(String[] args) throws Exception {
JAXBContext context = JAXBContext.newInstance(Employee.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Employee object = new Employee();
object.setCode("CA");
object.setName("Cath");
object.setSalary(300);
m.marshal(object, System.out);
}
}
#XmlRootElement
class Employee {
private String code;
private String name;
private int salary;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int population) {
this.salary = population;
}
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employee>
<code>CA</code>
<name>Cath</name>
<salary>300</salary>
</employee>
From: http://www.java2s.com/Code/JavaAPI/javax.xml.bind.annotation/javaxxmlbindannotationXmlRootElement.htm
For the benefit of anyone else hitting this thread, I imagine you did the following:
#XmlRootElement
public class Element {
#XmlAttribute
private String uid = "asdf";
#XmlValue
private String value = "value";
}
For More Information
http://bdoughan.blogspot.com/2011/06/jaxb-and-complex-types-with-simple.html
There are various tools that you can use to do this. XStream (http://x-stream.github.io/) is a reasonably easy tool to use that allows you to use annotations to determine the schema of XML that is created.

Categories