Why does this serialization logic fail with 'unmatched serializable field(s) declared'? - java

A reproducible example:
package test;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
public class mySerializable implements Serializable {
private static int f;
private static int g;
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("f", Integer.class),
new ObjectStreamField("g", Integer.class),
};
public static void main(String[] args) {
save();
}
public static void save() {
try {
FileOutputStream fileOut = new FileOutputStream("config" + ".ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(new mySerializable());
out.close();
fileOut.close();
} catch (Exception ex) {
System.out.println("save()" + ex.getLocalizedMessage()); }
}
public static int getF() {
return f;
}
public static void setF(int f) {
mySerializable.f = f;
}
public static int getG() {
return g;
}
public static void setG(int g) {
mySerializable.g = g;
}
}
The program prints:
save(): test.mySerializable; unmatched serializable field(s) declared

You've got two problems:
f and g are static; static fields aren't serialized.
They're also of type int, not Integer.
Make them non-static, and refer to them using int.class.
Ideone demo

Related

How can I extract the public constructors, methods, and variables from a class file [duplicate]

Suppose that I have a .class file, can I get all the methods included in that class ?
Straight from the source: http://java.sun.com/developer/technicalArticles/ALT/Reflection/
Then I modified it to be self contained, not requiring anything from the command line. ;-)
import java.lang.reflect.*;
/**
Compile with this:
C:\Documents and Settings\glow\My Documents\j>javac DumpMethods.java
Run like this, and results follow
C:\Documents and Settings\glow\My Documents\j>java DumpMethods
public void DumpMethods.foo()
public int DumpMethods.bar()
public java.lang.String DumpMethods.baz()
public static void DumpMethods.main(java.lang.String[])
*/
public class DumpMethods {
public void foo() { }
public int bar() { return 12; }
public String baz() { return ""; }
public static void main(String args[]) {
try {
Class thisClass = DumpMethods.class;
Method[] methods = thisClass.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i].toString());
}
} catch (Throwable e) {
System.err.println(e);
}
}
}
To know about all methods use this statement in console:
javap -cp jar-file.jar packagename.classname
or
javap class-file.class packagename.classname
or for example:
javap java.lang.StringBuffer
You can use the Reflection API
package tPoint;
import java.io.File;
import java.lang.reflect.Method;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
public class ReadClasses {
public static void main(String[] args) {
try {
Class c = Class.forName("tPoint" + ".Sample");
Object obj = c.newInstance();
Document doc =
DocumentBuilderFactory.newInstance().newDocumentBuilder()
.parse(new File("src/datasource.xml"));
Method[] m = c.getDeclaredMethods();
for (Method e : m) {
String mName = e.getName();
if (mName.startsWith("set")) {
System.out.println(mName);
e.invoke(obj, new
String(doc.getElementsByTagName(mName).item(0).getTextContent()));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

Save an enum in RandomAccessFile

Ok, I have a class called Encuadernacion.java
public enum Encuadernacion {
NONE("Ninguno"),
RUSTICA("Rustica"),
CARTONE("Cartone"),
PIEL("Piel"),
ESPIRAL("Espiral"),
GRAPADA("Grapada");
private final String ENCUADERNAR;
Encuadernacion(String descripcion){
this.ENCUADERNAR = descripcion;
}
public String getDescripcion(){
return ENCUADERNAR;
}
}
and then the book creation called Libro.java
public class Libro implements Serializable{
private Encuadernacion encuadernado;
public void setEncuadernado(int encuadernar){
this.encuadernado = Encuadernacion.values()[encuadernar];
//this encuadernar index is handled on another class.
}
public String getEncuadernacion(){
return encuadernado.getDescripcion();
}
#Override
public String toString(){
return encuadernado.getDescripcion();
}
and then the main class named Test.java
public class Test{
public static void main(String[] args)throws IOException{
RandomAccessFile fichero = null;
try {
fichero = new RandomAccessFile("BIBLIO.DAT", "rw");
}catch (FileNotFoundException e){
System.out.printf("Mensaje: %s", e.getMessage());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
When I write the enum into BIBLIO.DAT, it gets written as a string, It's Ok until this step. But when I want to read it, I create a new book while read those words.
Listar.java
public class Listar {
public static void lista(RandomAccessFile fichero)throws IOException, ClassNotFoundException{
try{
while(true){
Libro libro=new Libro();
libro.setEncuadernado(fichero.readUTF());
System.out.println(libro.toString());
}
}catch(EOFException e){
if(fichero!=null) fichero.close();
}
}
}
In this libro.setEncuadernado(fichero.readUTF()); This is not possible because this has to be a value from Encuadernacion SOMETHING;
How can I solve that? Transforming this string into enum value, or writing in diferent way the enum into BIBLIO.DAT, but RandomAccessFile has not a method to do that.
the code is cut for better reading.
I think it is worth to try:
public void setEncuadernado(String encuadernar){
this.encuadernado = Encuadernacion.valueOf(encuadernar);
//this encuadernar index is handled on another class.
}
in a Libro class. But as your code is not a MCVE, I didn't test it.
Solved like this.
public static String listarEncuadernados(){
Scanner scann=new Scanner(System.in);
int i =0;
for (Encuadernacion tipos: Encuadernacion.values()){
System.out.printf("\n%d.- %s", i, tipos.getDescripcion());
i++;
}
System.out.println();
int op = scann.nextInt();
return Encuadernacion.values()[op].getDescripcion();
}
public class Libro implements Serializable{
public void setEncuadernado(String encuadernar){
this.encuadernado = Encuadernacion.valueOf(encuadernar.toUpperCase());
}
#Override
public String toString(){
return encuadernado.getDescripcion();
}
}
public class Listar {
public static void lista(RandomAccessFile fichero)throws IOException, ClassNotFoundException{
try{
while(true){
Libro libro=new Libro();
libro.setEncuadernado(fichero.readUTF());
System.out.println(libro.toString());
}
}catch(EOFException e){
if(fichero!=null) fichero.close();
}
}
}

Write a object with ObjectOutputStream

It is clear that I can't write the Test object to the file Test.dat, my question is what exactly is the reason that it will not succeed?
import java.io.*;
public class Test {
private int a = 10;
private double b = 7.5;
private String m = "valu";
public static void main(String[] args) {
Test t = new Test();
ObjectOutputStream output = ObjectOutputStream(new FileOutputStream("Test.dat"));
output.writeObject(t);
output.close();
}
}
Apart from new key word, you forgot to implement Serializable
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Test implements Serializable{
private int a = 10;
private double b = 7.5;
private String m = "valu";
public static void main(String[] args) throws IOException {
Test t = new Test();
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("Test.dat"));
output.writeObject(t);
output.close();
}
}
Try
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("Test.dat"));
You had missed the "new" so the compiler is looking for a static method rather than the constructor

ASM Code Error when main method is defined

I am getting the error:
Prints the ASM code to generate the given class.
Usage: ASMifier [-debug]
From what I gather this is because I do not have the main method declared but this is clearly defined in one of my classes: Could this be a build error?
Main Class
package com.exacttarget.client;
public class Main {
public static void main(String[] args) {
System.out.println("Test");
}
}
PropertiesUtil Class
package com.exacttarget.client;
import java.util.Properties;
public class PropertiesUtil {
private static PropertiesUtil _instance = new PropertiesUtil();
Properties properties;
public void init() {
try {
if (properties == null || properties.isEmpty()) {
java.io.InputStream inConfig = PropertiesUtil.class.getClassLoader().getResourceAsStream("props.xml");
properties.loadFromXML(inConfig);
//properties.load(inConfig);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
private PropertiesUtil() {
super();
properties = new Properties();
init();
}
public static PropertiesUtil getInstance() {
return _instance;
}
public String getProperty(String key) {
return properties.getProperty(key);
}
}
PWCBHandler Class
package com.exacttarget.client;
import java.io.IOException;
import javax.security.auth.callback.*;
import org.apache.ws.security.WSPasswordCallback;
public class PWCBHandler implements CallbackHandler {
public PWCBHandler() {
}
#Override
public void handle(Callback callbacks[]) throws IOException, UnsupportedCallbackException {
for(int i = 0; i < callbacks.length; i++)
if(callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
pc.setIdentifier(PropertiesUtil.getInstance().getProperty("username"));
pc.setPassword(PropertiesUtil.getInstance().getProperty("password"));
//pc.setPassword("welcome#1");
} else {
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}
}
}

Accessing static variable from another class

My problem is simple: I need to access variable history (which is declared in class BinaryServer) from another class.I'm using more classes to run this code.It's just simple client and server made of sockets.Client sends to server binary code/text and server translates it to text/binary code and sends it back to client.I can provide all classes if needed.
BinaryServer class
import java.net.*;
import java.util.ArrayList;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import graphics.gui;
public class BinaryServer extends gui implements ActionListener,Runnable
{
private ServerSocket server;
private Socket client;
public String text;
private BufferedReader reader;
public static ArrayList<String> history;
public static String binary_letter;
public static String[] letter;
public static int i;
public static String[] binary;
public static String sendback;
public static void main(String[] args)throws IOException
{
BinaryServer instance=new BinaryServer();
gui.buildframe(310,360,"Binary translator server");
gui.buildpane(300,300,true);
gui.buildbutton(300,20,"Translate");
instance.server(63400);
}
public void server(int port)throws IOException
{
history=new ArrayList<String>(100);
server=new ServerSocket(port);
button.addActionListener(this);
while(true)
{
client=server.accept();
reader=new BufferedReader(new InputStreamReader(client.getInputStream()));
text=reader.readLine();
history.add(text);
message.setText(message.getText()+"\n"+text+": ");
}
}
#Override
public void actionPerformed(ActionEvent e)
{
Thread response=new Thread(new BinaryServer());
if(text.contains("0"))
{
int length=text.length();
letter=new String[length+1];
sendback="";
int begin=-8;
int end=0;
for(i=1;i<=length/8;i++)
{
begin=begin+8;
end=i*8;
binary_letter=text.substring(begin,end);
Libary.translate();
message.setText(message.getText()+letter[i]);
sendback=sendback+letter[0+i];
}
}
else
{
int length=text.length();
letter=new String[length+1];
binary=new String[length+1];
sendback="";
for(i=1;i<=length;i++)
{
letter[i]=text.substring(i-1,i);
Libary.encode();
message.setText(message.getText()+binary[i]);
sendback=sendback+binary[0+i];
}
}
response.start();
}
public void run()
{
try
{
Socket feedback=new Socket("localhost",63403);
PrintWriter writer=new PrintWriter(feedback.getOutputStream(),true);
writer.println(sendback);
feedback.close();
return;
}
catch(IOException exc)
{
System.out.println("");
}
}
}
BinaryHistory class (The one I want access variable from)
public class BinaryHistory
{
public static void main(String[] args)
{
show();
}
public static void show()
{
System.out.println(BinaryServer.history);
}
When I access variable history from class BinaryHistory, it's alway null.
If you only declare the variable, regardless of the type or whether or not it's static, it will get a default value of null.
You have to initialize the variable too:
public static ArrayList<String> history = new ArrayList<>();

Categories