I am trying to write a custom converter for a byte[] in Simple XML. It is working half way meaning invoking the write method but not the read. Can someone point out why??
Here is my simple xml annotated object
#Root
public class Device implements Serializable
{
private final static long serialVersionUID = 1L;
#Element
#Convert(ByteArrayConverter.class)
protected byte[] imageRef;
public byte[] getImageRef() {
return imageRef;
}
public void setImageRef(byte[] imageRef) {
this.imageRef = imageRef;
}
Here is my custom converter
public class ByteArrayConverter implements Converter<byte[]>
{
#Override
public byte[] read(InputNode node) throws Exception
{
//put a break point here BUT Code not getting here
("I am here in read")
String s = node.getValue();
return Base64.decode(s);
}
#Override
public void write(OutputNode node, byte[] byteArray) throws Exception
{
("I am here in write")
node.setValue(Base64.encode(byteArray))
}
Here is my serialization/deserialization code
Registry registry = new Registry();
Strategy strategy = new RegistryStrategy(registry);
Serializer serializer = new Persister(strategy);
try
{
registry.bind(byte[].class, ByteArrayConverter.class);
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Device device = new Device();
device.setImageRef(new byte[]{1,2,3});
File file = new File("myDevice.xml");
serializer.write(device, file);
Device readDevice = serializer.read(Device.class, file);
When I execute this in debugger I do see the debugger stopping in write method however it doesn't stop in read() method and hence I am not getting expected result. Any reason why this code do not stop in reading when we are constructing the object back??? Thanks
Related
My university professor shared this class with us (it's essentially a generic parser using Gson):
public abstract class GenericDAO<T> {
final Class<T> clase;
protected File archivo;
public GenericDAO(Class<T> clase, String file) throws Exception {
this.clase = clase;
this.archivo = new File(file);
this.archivo.createNewFile();
}
public List<T> getAll(Class<T> clase) throws Exception {
List<T> list = new ArrayList<T>();
FileReader f = new FileReader(archivo);
BufferedReader b = new BufferedReader(f);
Gson g = new Gson();
String line = "";
try {
while ((line = b.readLine()) != null && !line.equals("")) {
JsonParser parser = new JsonParser();
JsonObject jsonObject = parser.parse(line).getAsJsonObject();
list.add(g.fromJson(jsonObject, clase));
}
b.close();
} catch (Exception e) {
e.printStackTrace();
return list;
}
return list;
}
// a lot of other methods to read/write to json files
}
I created a class that inherits from it so I can read a Business from a file:
public class Business extends GenericDAO<Business> {
private String name;
// a lot of other members
// this was automatically generated by Intellij:
public Business(Class<Business> clase, String file) throws Exception {
super(clase, file);
}
}
Intellij automatically generated a constructor for it, but I don't understand it. Why does the constructor has a class as a parameter, do I have to pass an instance of itself to it? That doesn't make sense.
I would be grateful if you can point me to either some documentation to read through, or explain the pattern my professor is using.
Edit: to sum up, how do I instantiate my business class then? This is throwing an error:
Business client = new Business(Business, "path_to_json_file.json");
This wouldn't fit well in a comment: you could use a different style of constructor if you want. Replace this:
// this was automatically generated by Intellij:
public Business(Class<Business> clase, String file) throws Exception {
super(clase, file);
}
With this:
public Business(String file) throws Exception {
super( Business.class, file);
}
Which I think is more like your instructor may have intended.
I am starting to program a Code Generator for NetBeans 8, and I am having trouble figuring out the best way to test its invoke() method.
The code generator I want to test is basically like this:
(imports here)
public class MyCodeGenerator implements CodeGenerator {
private final JTextComponent textComponent;
private final CompilationController controller;
MyCodeGenerator(final Lookup context) {
textComponent = context.lookup(JTextComponent.class);
controller = context.lookup(CompilationController.class);
}
#Override
public String getDisplayName() {
return "Generate Some Code...";
}
/**
* This will be invoked when user chooses this Generator from Insert Code
* dialog
*/
#Override
public void invoke() {
if (textComponent != null && controller != null) {
controller.toPhase(Phase.RESOLVED);
//do more things with the source code;
}
}
}
I want to use a mocked (Mockito) object for Lookup, to pass to the MyCodeGenerator's constructor. The mock should return the JTextComponent and the CompilationController.
I know I can provide a JTextComponent with the test code, but I hit the wall when I need to provide a CompilationController.
I can create a temporary java source file with the same content as the JTextComponent, but I could not find a way to create a CompilationController (or WorkingCopy) from it.
This is what I tried so far (my test method):
#Test
public void testInvoke() throws ParseException, IOException {
System.out.println("invoke");
final ExtractControllerTask extractTask = new ExtractControllerTask(
Phase.RESOLVED);
final StringBuilder builder = new StringBuilder(100);
final JTextComponent textComponent;
final Document document;
final FileObject javaTestFile;
final OutputStream outputStream;
final JavaSource source;
builder.append("public class Clazz {");
builder.append("private int a = 2;");
builder.append("}");
textComponent = new JTextArea(builder.toString());
document = textComponent.getDocument();
document.putProperty(BaseDocument.MIME_TYPE_PROP, "text/x-java");
javaTestFile = FileUtil.createData(new File(
"/tmp/javaTestSourceFile.java"));
outputStream = javaTestFile.getOutputStream();
outputStream.write(builder.toString().getBytes());
outputStream.flush();
source = JavaSource.forFileObject(javaTestFile);
assertNotNull(source);
source.runUserActionTask(extractTask, true);
assertNotNull(extractTask.controller); //FAILS HERE
}
This is the code for ExtractControllerTask:
private static class ExtractControllerTask implements
Task<CompilationController> {
private final Phase targetPhase;
private CompilationController controller;
private ExtractControllerTask(final Phase phase) {
this.targetPhase = phase;
}
public void run(final CompilationController compControler) {
try {
compControler.toPhase(this.targetPhase);
this.controller = compControler;
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
}
What surprises me is that the run method in ExtractControllerTask is never called.
I really need to test my code but I can't find the proper way. Maybe the approach is completely wrong.
Can anyone suggest how to achieve this?
I've learnt how to unit test basic things within Android, e.g. getting and setting of methods as below etc. but when it comes to the more complex stuff like my actual code below, I'm a little flummoxed at what to do.
public class SurveyTest extends TestCase {
private Survey survey;
protected void setUp() throws Exception {
super.setUp();
survey = new Survey();
}
public void testGetId() {
long expected = (long) Math.random();
survey.setId(expected);
long actual = survey.getId();
Assert.assertEquals(expected, actual);
}
public void testGetTitle() {
String expected = "surveytitle";
survey.setTitle(expected);
String actual = survey.getTitle();
Assert.assertEquals(expected, actual);
}
My small code that I'm stuck on how to Junit Test in the format as above:
public abstract class PrimaryModel extends Observable implements Serializable{
protected void notifyModelChange()
{
setChanged();
notifyObservers();
}
public String serialize() throws IOException
{
ObjectOutputStream objOutStream = null;
ByteArrayOutputStream bytArrOutStream = null;
try
{
bytArrOutStream = new ByteArrayOutputStream();
objOutStream = new ObjectOutputStream(bytArrOutStream);
objOutStream.writeObject(this);
}
finally
{
String main = new String(bytArrOutStream.toByteArray());
objOutStream.close();
bytArrOutStream.close();
return main;
}
}
public static PrimaryModel deserialize(String data) throws IOException, ClassNotFoundException
{
ObjectInputStream objInputStream = new ObjectInputStream(new ByteArrayInputStream(data.getBytes()));
PrimaryModel obj = (PrimaryModel) objInputStream.readObject();
objInputStream.close();
return obj;
}
}
Something like a serialize/deserialize pair of methods is generally easily tested. You need to know that a round trip returns an object which is equivalent to the original.
private static class PrimaryModelSubclass extends PrimaryModel {
/* add methods as needed */
}
final PrimaryModel original = new PrimaryModelSubclass(7, "some string", 43.7);
final PrimaryModel wellTravelled = PrimaryModel.deserialize(original.serialize());
assertEquals(original, wellTravelled);
You will need hashCode and equals methods to be correctly defined as well.
Updated in response to comment
I'm trying to serialize this Configuration object, but for the life of me I can't get it. I've checked everywhere including StackOverflow. Any help would be greatly appreciated.
Serialization Code:
public void serialize(String outFile)
throws IOException {
Configuration config = new Configuration().getConfiguration();
System.out.println(config.email);
try
{
FileOutputStream outputFile =
new FileOutputStream("/home/jason/Desktop/config.ser");
ObjectOutputStream objectOutput = new ObjectOutputStream(outputFile);
objectOutput.writeObject(config);
objectOutput.close();
outputFile.close();
}catch(IOException i)
{
i.printStackTrace();
}
System.out.println(config);
}
public void deSerialize()
throws FileNotFoundException, IOException, ClassNotFoundException {
Configuration config = new Configuration().getConfiguration();
try
{
FileInputStream inputFile = new FileInputStream("/home/jason/Desktop/config.ser");
ObjectInputStream objectInput = new ObjectInputStream(inputFile);
config = (Configuration) objectInput.readObject();
config.setConfiguration(config);
objectInput.close();
inputFile.close();
}catch(Exception e)
{
e.printStackTrace();
}
System.out.println(config);
}
And then I call it with the following code:
DataStore data = new DataStore().getInstance();
try {
data.deSerialize();
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
DataStore is a simple singleton, and takes no input parameters. It doesn't have any real variables, but simply employs the serialization functions.
Finally, here is my Configuration code:
public class Configuration implements Serializable{
private static final long serialVersionUID = 1388190376766023647L;
public static String email = "";
private static String ip = "";
private static String password = "";
private static String importNumber;
private static Configuration configuration;
private static int singleton = 0;
public String value_of_da_message;
public Configuration()
{}
public Configuration getConfiguration()
{
if(singleton == 0){
configuration = new Configuration();
singleton++;
return configuration;
}
else
return configuration;
}
public void setConfiguration(Configuration config)
{
configuration = config;
}
Any clue on where I'm going wrong? Thanks for the help.
Have a look here: Java static serialization rules?
Change your fields to be instance fields, which would better fit the singleton approach anyways.
The fields might be serialized but deserialization normally ignores static fields.
Additionally, it looks like you're reading to the temporary object:
config.setConfiguration(config);
This uses the read object twice and doesn't set the data of the singleton unless you keep that a static field (i.e. configuration in the Configuration class is the reference to the singleton and needs to be static)
Update:
Another hint: the static variable singleton might cause problems and is unneeded anyway. Just check configuration == null instead of singleton == 0.
Hint:
I try to help you with serialization in general, but in your special case you might want to use Properties instead which have built-in serialization features (.properties- and xml-files supported) and which are meant for configuration.
I'm trying to get Simple to play nice with XMLGregorianCalendar. In so doing I've created a Matcher and Transform:
public class MyMatcher implements Matcher {
#Override
public Transform<?> match(#SuppressWarnings("rawtypes") final Class type) throws Exception {
if (type.equals(XMLGregorianCalendar.class)) {
return new XMLGregorianCalendarTransform();
}
return null;
}
}
and
public class XMLGregorianCalendarTransform implements Transform<XMLGregorianCalendar> {
#Override
public XMLGregorianCalendar read(final String value) throws Exception {
return DatatypeFactory.newInstance().newXMLGregorianCalendar(value);
}
#Override
public String write(final XMLGregorianCalendar value) throws Exception {
return value.toXMLFormat();
}
}
When this code is used to deserialize, it works great:
final Serializer serializer = new Persister(new MyMatcher());
obj = serializer.read(type, new ByteArrayInputStream(xml.getBytes(Charset.forName(UTF8_ENCODING))));
Unfortunately when I try to use it to serialize, it doesn't work, it throws the Failed to create xml string for the object.
org.simpleframework.xml.transform.TransformException: Transform of class com.sun.org.apache.xerces.internal.jaxp.datatyp
e.XMLGregorianCalendarImpl not supported error, my Transform's write method is never called (check by break point).
Here's the code I use to serialize:
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
os = new DataOutputStream(baos);
final Serializer serializer = new Persister(new MyMatcher());
serializer.write(this, os);
os.flush();
xmlString = new String(baos.toByteArray(), Charset.forName(UTF8_ENCODING));
The write method throws the exception. I've used Serialization third-party classes with Simple XML (org.simpleframework.xml) as a reference, and it's what got me to the deserialization working, but now I'm stuck. I'm not sure how to proceed.
Any help is appreciated.
It turns out the answer was in the question. The error stated XMLGregorianCalendarImpl not supported. This is not what my Matcher checked for. I just had to change:
if (type.equals(XMLGregorianCalendar.class)) {
to
if (XMLGregorianCalendar.class.isAssignableFrom(type)) {
I hope this helps someone.