I'm trying to implement the Externalizable interface to store the data using the LWUIT-IO's storage. This worked great for simple objects that are composed of Strings, booleans and ints.
However, I have an object that is composed of these types, but also of a Vector of the above mentioned Externalizable object. This seem to mess up the process and I get nothing when I try to retrieve the object from storage.
I assumed it was like the Serializable interface and that the Externalizable objects inside the main object are automatically handled. I'm not sure if this is true, or why it's failing.
The object inside the object is:
public class Song implements Externalizable{
String name = "examplesongname";
public void externalize(DataOutputStream out) throws IOException {
out.writeUTF(name);
}
public void internalize(int version, DataInputStream in) throws IOException {
name = in.readUTF();
}
public String getObjectId() {
return "pat.objects.Song";
}
public int getVersion() {
return 1;
}
}
The containing object is as follows:
public class Playlist implements Externalizable{
String name = "exampleplaylistname";
Vector songs = new Vector();
public void externalize(DataOutputStream out) throws IOException {
out.writeUTF(name);
out.write(songs.size());
Enumeration allItems = songs.elements();
while(allItems.hasMoreElements()){
Externalizable nextItem = (Externalizable) allItems.nextElement();
nextItem.externalize(out);
}
}
public void internalize(int version, DataInputStream in) throws IOException {
name = in.readUTF();
int size = in.readInt();
songs= new Vector();
for(int currentIndex = 0; currentIndex < size; currentIndex++){
Object nextItem = new Object();
((Externalizable)nextItem).internalize(version, in);
songs.addElement(nextItem);
}
}
}
public String getObjectId() {
return "pat.objects.Playlist";
}
public int getVersion() {
return 1;
}
}
What am I doing wrong or missing that is making the Playlist (containing object) fail to be stored while if I try to store the first one by itself it works?
Please note that the overriding methods are different that normal Java since this is the LWUIT version of Externalizable interface.
You need to use Util.register(...) to register these classes as externalizable when your app starts up.
Also the call directly to externalize isn't correct. You should use Util.writeObject/readObject to write another externalizable object (with its own version number). You can then avoid the loop over the vector which would be redundant and just write the whole vector.
I would also suggest using Util.readUTF/writeUTF which support null strings as well.
As a sidenote, I'd suggest migrating to Codename one since LWUIT is no longer maintained by anyone. Also Steve Hannah has a nice writeup on externalization is Codename One which is pretty similar to LWUIT (although it now supports Lists and Maps): http://www.shannah.ca/blog/?p=234
Related
I'm essentially asking the same as this old question, but for Java 14 instead of Java 8. To spare answerers the trouble of navigating to the old question, I'll rephrase it here.
I want to get the name of a function from a referenced method. The following Java code should give you the idea:
public class Main
{
public static void main(String[] args)
{
printMethodName(Main::main);
}
private static void printMethodName(Consumer<String[]> theFunc)
{
String funcName = // somehow get name from theFunc
System.out.println(funcName)
}
}
The equivalent in C# would be:
public class Main
{
public static void Main()
{
var method = Main.Main;
PrintMethodName(method)
}
private static void PrintMethodName(Action action)
{
Console.WriteLine(action.GetMethodInfo().Name);
}
}
According to the accepted answer of the old question, this was not possible in Java 8 without considerable work, such as this solution. Is there a more elegant solution in Java 14?
Getting a method info from a method reference never was a goal on the JDK developer’s side, so no effort was made to change the situation.
However, the approach shown in your link can be simplified. Instead of serializing the information, patching the serialized data, and restoring the information using a replacement object, you can simply intercept the original SerializedLambda object while serializing.
E.g.
public class GetSerializedLambda extends ObjectOutputStream {
public static void main(String[] args) { // example case
var lambda = (Consumer<String[]>&Serializable)GetSerializedLambda::main;
SerializedLambda sl = GetSerializedLambda.get(lambda);
System.out.println(sl.getImplClass() + " " + sl.getImplMethodName());
}
private SerializedLambda info;
GetSerializedLambda() throws IOException {
super(OutputStream.nullOutputStream());
super.enableReplaceObject(true);
}
#Override protected Object replaceObject(Object obj) throws IOException {
if(obj instanceof SerializedLambda) {
info = (SerializedLambda)obj;
obj = null;
}
return obj;
}
public static SerializedLambda get(Object obj) {
try {
GetSerializedLambda getter = new GetSerializedLambda();
getter.writeObject(obj);
return getter.info;
} catch(IOException ex) {
throw new IllegalArgumentException("not a serializable lambda", ex);
}
}
}
which will print GetSerializedLambda main. The only newer feature used here, is the OutputStream.nullOutputStream() to drop the written information immediately. Prior to JDK 11, you could write into a ByteArrayOutputStream and drop the information after the operation which is only slightly less efficient. The example also using var, but this is irrelevant to the actual operation of getting the method information.
The limitations are the same as in JDK 8. It requires a serializable method reference. Further, there is no guaranty that the implementation will map to a method directly. E.g., if you change the example’s declaration to public static void main(String... args), it will print something like lambda$1 when being compiled with Eclipse. When also changing the next line to var lambda = (Consumer<String>&Serializable)GetSerializedLambda::main;, the code will always print a synthetic method name, as using a helper method is unavoidable. But in case of javac, the name is rather something like lambda$main$f23f6912$1 instead of Eclipse’s lambda$1.
In other words, you can expect encountering surprising implementation details. Do not write applications relying on the availability of such information.
I'm using listeners provided by Pircbotx (https://github.com/pircbotx/pircbotx/wiki/Documentation) to detect when a command is found in Twitch chat, and I am trying to use a different method depending on which Command is called (format is !command). Classes used: Listeners, Command.
Commands are stored in an array of Command objects, comprised of one String (name). Each Command object will ultimately use its own method that will be defined in the Command class. The Listeners object when instantiated will immediately place every element of the array into a hash table (commands).
When Listeners detects a message, it is stored using a local String variable (msg). When this happens, a loop iterates through the Command object array, and then.... is supposed to call the method that corresponds to that particular object, in this case Command.addDeath(). That's where I'm stuck.
I was previously using a bunch of if statements for my listeners, but when there's a bunch of commands things will get really, really messy. Apologies in advance if the formatting in my code block is weird, I'm pretty new to utilizing Stackverflow, and I'm also a Java novice that's learning as I go along. After looking at the code again, it would appear I don't really need the hash table - but I'm leaving it in there just in case you guys have any better ideas for what to do with them.
public class Listeners {
String name;
String message;
private static MessageEvent event;
Command [] commandNames = {new Command("!clearchat", new Command("!addDeath")};
Hashtable<String, Command> commands = new Hashtable<String, Command>();
public Listeners() {
for (int i = 0; i < commandNames.length; i++) {
commands.put(commandNames[i].name, new Command(commandNames[i].name));
}
if (event.getMessage() != null) {
String msg = event.getMessage();
for (int x = 0; x < commandNames.length; x++ ) {
if (msg.startsWith(commandNames[x].name)) {
// call Command method here
}
}
}
}
And here is the Command class:
public class Command {
String name;
public Command(String name) {
this.name = name;
}
public static void addDeath() {
DeathCounter.addDeath();
Listeners.sendMessage("Death Counter: " + DeathCounter.getDeaths());
}
}
You can use an interface for your commands:
public interface Command {
public abstract void execute();
}
Then have your commands implement the interface:
public class DeathCommand implements Command {
#Override
public void execute() {
DeathCounter.addDeath();
Listeners.sendMessage("Death Counter: " + DeathCounter.getDeaths());
}
}
In your listener class, map the command strings to instances of the corresponding command:
public class Listeners {
String name;
String message;
private static MessageEvent event;
static Map<String, Command> commands = new HashMap<>();
static {
commands.put("!addDeath", new DeathCommand());
}
public Listeners() {
if (event.getMessage() != null) {
String msg = event.getMessage();
Optional<String> key = commands.keySet().stream().filter(k -> msg.startsWith(k)).findFirst();
key.ifPresent(s -> commands.get(s).execute());
}
}
}
I replaced your Hashtable with a HashMap which is better in most ways (but is used the same way).
I'm a bit skeptical about having the map as a static member, but since I'm not familiar with your use case I leave that bit as is.
Edit
All Java classes have a default constructor (with no parameters) unless you write your own constructor (you have to write the default one yourself if you still want it). Interfaces don't have constructors since they can't be instantiated directly. They just specify methods that implementing classes must have. This allows you to have references (named fields/variables) of the interface type and be able to call the methods without knowing, or having to know, which implementation it is.
Example:
Command com = new DeathCommand();
com.execute(); // <- this will run the execute() code in the DeathCommand class
Command com2 = new SomeOtherCommand();
com2.execute(); // <- this will run the execute() code in the SomeOtherCommand class
The above code for Command is complete. There is nothing more. As for DeathCommand, and other implementations, you'll need to add what code is needed.
Each class and interface goes in it's own file named as the type:
Command.java
DeathCommand.java
Regarding HashTable vs HashMap. I should have said that it's better to use Map and it's implementations. If you need thread safety, use ConcurrentHashMap as agilob pointed out since regular HashMap is not thread safe.
I currently have class which have some fields initialized in declaration, like this:
public class SomeClass implements Externalizable {
private long id;
private final List<Hit> hits = new ArrayList<>();
#Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeLong(id);
out.writeInt(hits.size());
for (int i = 0; i < hits.size(); i++) {
out.writeObject(hits.get(i));
}
}
#Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
id = in.readLong();
int size = in.readInt();
for (int i = 0; i < size; i++) {
hits.add((Hit) in.readObject()); //<--Nullpointer here, hits == null
}
}
}
And this class is used in filebased chronicle-map configured like this:
ChronicleMap<Long, SomeClass> storage = ChronicleMapBuilder
.of(Long.class, SomeClass.class)
.averageValueSize(avgEntrySize)
.entries(entries)
.createPersistedTo(new File(path));
The problem is that when I restart my application I get NullpointerException when chronicle tries to read saved map, because hits field wasn't initialized, meaning it is null.
I did some investigation and found that before calling readExternal chronical creates object of this class using UNSAFE.allocateInstance(in ExternalizableMarshaller):
protected E getInstance() throws Exception {
return (E) NativeBytes.UNSAFE.allocateInstance(classMarshaled);
}
So basically this is the reason why its not initialized. What I am trying to understand why it is using such approach instead of MethodHandle or reflection?
And maybe there is another way to fix this without modifying SomeClass, like some chronicle configuration property maybe?
This appears to be an issue with version 2.x which is no longer supported.
In version 3.x it should call the default constructor if one exists. It will use Unsafe if there is no default constructor. I have added a test case which shows this works in 3.x
https://github.com/OpenHFT/Chronicle-Map/blob/master/src/test/java/net/openhft/chronicle/map/externalizable/ExternalizableTest.java
For version 2.x I suggest you need to check whether the list is null and set it as needed.
I have a class that creates index cards, and within it, I have an instance variable that is a static HashMap that stores all the instances created.
I have been thinking a lot about it and I thought that the methods that handle the opperations over that HashMap should go in a different class, because those methods don't opperate directly over any index card, they opperate over the list of index cards.
This way, I would have an IndexCard class, and an ListAdministrator class. And both classes would handle different functions.
The problem is that this new class (ListAdministrator) would only have static methods, because there is only one list and there is no reason to create any new list of index cards, I only need one.
Should I move those methods to another class or should I keep it like this? Is that a good practice?
This is the code:
class IndexCard {
public static HashMap <String, IndexCard> list = new HashMap <> ();
public String name;
public String address;
public String phone;
public String email;
public LocalDate dateRegister;
IndexCard(String name, String dni, String address, String phone, String email) {
this.name = name;
this.address = address;
this.phone = phone;
this.email = email;
dateRegister = LocalDate.now();
if (Utils.validarDni(dni) && !list.containsKey(dni)) {
list.put(dni, this);
} else {
throw new InvalidParameterException ("Error when entering the data or the DNI has already been previously registered");
}
}
/**
* Update the data of the selected card.
*/
public void update() throws IllegalAccessException {
String key = getKeyWithObject(this);
Scanner reader = new Scanner(System.in);
Field[] fields = this.getClass().getFields();
for (Field field: fields) {
String nameField = Utils.splitCamelCase(field.getName());
if (!Modifier.isStatic(field.getModifiers()) && (field.getType()).equals(String.class)) {
System.out.println ("Enter new " + nameField);
String value = reader.nextLine().trim();
field.set(this, value);
}
}
reader.close();
list.put(key, this);
System.out.println("Updated data \n \n");
}
/**
* Delete the selected card.
*/
public void delete() throws IllegalAccessException {
String key = getKeyWithObject(this);
Field [] fields = this.getClass().getFields();
for (Field field: fields) {
if (!Modifier.isStatic(field.getModifiers())) {
field.set(this, null);
}
}
list.remove(key);
}
/**
* Displays the data of the selected card on screen.
*/
public void print() throws IllegalAccessException {
Field [] fields = this.getClass().getFields();
for (Field field: fields) {
if (!Modifier.isStatic(field.getModifiers())) {
String nameFieldConSpaces = Utils.splitCamelCase(field.getName());
Object value = field.get(this);
System.out.println(nameFieldConSpaces + ":" + value);
}
}
}
/**
* Print all the entries of the desired sublist with the ID, Name and phone number.
*/
public static <T extends IndexCard> void SubClasslist (Class <T> subClass) {
for (HashMap.Entry <String, IndexCard> entry: list.entrySet ()) {
String key = entry.getKey ();
IndexCard card = entry.getValue ();
if (card.getClass().equals(subClass)) {
System.out.println ("ID:" + key + "| Name:" + card.name + "| Phone:" + card.phone);
}
}
}
/**
* Returns the object stored in the list of cards when entering the corresponding key.
*/
public static IndexCard GetObjetWithKey(String key) {
try {
return list.get(key);
} catch (IllegalArgumentException e) {
System.out.println (e + ": The indicated key does not appear in the database.");
return null;
}
}
/**
* Obtain the Key when entering the corresponding card.
*/
public static String getKeyWithObject (Object obj) {
for (HashMap.Entry <String, IndexCard> entry: list.entrySet()) {
if (obj.equals(entry.getValue())) {
return entry.getKey();
}
}
throw new IllegalArgumentException ("The indicated data does not appear in the database, and therefore we could not obtain the key.");
}
/**
* Returns a list of cards when entering the main data of the card.
* #param data Corresponds to the identifying name of the file.
*/
public static ArrayList <IndexCard> SearchByName (String data) {
try {
ArrayList <IndexCard> listCards = new ArrayList <> ();
for (HashMap.Entry <String, IndexCard> entry: list.entrySet ()) {
IndexCard card = entry.getValue ();
String name = entry.getValue().name;
if (name.toLowerCase().trim().contains(data.toLowerCase().trim())) {
listCards.add(card);
}
}
return listCards;
} catch (IllegalArgumentException e) {
System.out.println (e + "The indicated data does not appear in the database, you may have entered it incorrectly.");
return null;
}
}
}
All those static methods are what I would put in the new class.
This is how the new class ListAdministrator would look. It would not even need a constructor.
class ListAdministrator{
public static HashMap <String, IndexCard> list = new HashMap <> ();
/**
* Print all the entries of the desired sublist with the ID, Name and phone number.
*/
public static <T extends IndexCard> void SubClasslist (Class <T> subClass) {
for (HashMap.Entry <String, IndexCard> entry: list.entrySet ()) {
String key = entry.getKey ();
IndexCard card = entry.getValue ();
if (card.getClass().equals(subClass)) {
System.out.println ("ID:" + key + "| Name:" + card.name + "| Phone:" + card.phone);
}
}
}
/**
* Returns the object stored in the list of cards when entering the corresponding key.
*/
public static IndexCard GetObjetWithKey(String key) {
try {
return list.get(key);
} catch (IllegalArgumentException e) {
System.out.println (e + ": The indicated key does not appear in the database.");
return null;
}
}
/**
* Obtain the Key when entering the corresponding card.
*/
public static String getKeyWithObject (Object obj) {
for (HashMap.Entry <String, IndexCard> entry: list.entrySet()) {
if (obj.equals(entry.getValue())) {
return entry.getKey();
}
}
throw new IllegalArgumentException ("The indicated data does not appear in the database, and therefore we could not obtain the key.");
}
/**
* Returns a list of cards when entering the main data of the card.
* #param data Corresponds to the identifying name of the file.
*/
public static ArrayList <IndexCard> SearchByName (String data) {
try {
ArrayList <IndexCard> listCards = new ArrayList <> ();
for (HashMap.Entry <String, IndexCard> entry: list.entrySet ()) {
IndexCard card = entry.getValue ();
String name = entry.getValue().name;
if (name.toLowerCase().trim().contains(data.toLowerCase().trim())) {
listCards.add(card);
}
}
return listCards;
} catch (IllegalArgumentException e) {
System.out.println (e + "The indicated data does not appear in the database, you may have entered it incorrectly.");
return null;
}
}
}
You should keep the concerns of managing the IndexCards and the IndexCards themselves separate because of the Single Responsibility Principle. Furthermore the ListAdministrator should handle everything that deals with the management of the IndexCards, also deletion and creation of the managed objects.
The name ListAdministrator is somehow not meeting the point as it does not administrate lists, maybe use something like IndexCardRegistry.
To deal with concurrency you could use a ConcurrentMap as your main data storage.
Having ListAdministrator all static might come in handy if your IndexCards need access to it or other IndexCards, but this would not be the best design. Do they need to know anyway? From my understanding the IndexCards could be simple POJOs that contain only data and no logic at all.
On the other hand with an all-static ListAdministrator you will not be able to use two instances of managed objects at the same time in the future without major refactoring your code. Even if you never would expect this today a well defined object registry that can handle any object might come in handy in projects to come. Therefore I would rather use real instances for the ListAdministrator (and program against it's interface to stay flexible).
In more detail referring to your comments:
The idea of this approach is to keep concerns clearly separated, which will make future changes to your code feasible in case the project grows (most projects tend to do so). My understanding is that the ListAdministrator should manage your IndexCards. In a way this is the same as Object Relational Mappers work, but at the moment your database is a HashMap. If you create an interface for ListAdministrator you may even swap out the HashMap with a database without having to change its clients.
On second investigation of your code I found that IndexCards not only store the data but as well have methods to update the data. This represents another break of the Single Responsibility Principle and should be dealt with. If the ListAdministrator would provide an update method for a given IndexCard it could be used by as many different clients you can think of without changing any code behind the ListAdministrators API. Your first client would be the command-line interface you already have programmed, the next might be a web service.
With an all-static ListAdministrator you have one static Class that manages one static data set. It will always only deal with IndexCards, everything you add will end up in the same HashMap (if allowed/compatible). Every part of your application with access to the class ListAdministrator would have full access to the data. If you needed another ListAdministrator (handling create, delete, update, search) for a different type you would have to refactor everything to accomodate this or start duplicating code. Why not create an instance based solution in the first place. You would have your repository for IndexCards, and could add new repositories at will.
Maybe this is over-engineering for your use case but in keeping the responsibilities clearly separated you will find out that many extensions of your code will happen orthogonal (not affecting existing code), and this is where the fun really begins. And how do you want to practice this if not with smaller projects.
More details about the reason of using interfaces for flexible code (in response to latest comment)
The short answer is: always code against an interface (as stated in numerous articles and java books). But why?
A Java interface is like a contract between a class and its clients. It defines some methods, but does not implement them itself. To implement an interface you define a class with class XYZ implements SomeInterface and the source code of the class does whatever it finds reasonable to answer to the methods defined in the interface. You try to keep the interface small, to contain only the essential methods because the smaller the interface is, the less methods you have to take into account when changes have to be made.
A common idiom in Java would be to define a List<T> return type (the interface) for a method, which most likely would be an ArrayList (concrete class), but could be a LinkedList (another concrete class) as well, or anything else that implements the List interface. By just returning the List interface you prevent your client to use other methods of the otherwise returned concrete class as well which would greatly reduce your freedom to change the internal implementation of your "ListProvider". You hide the internal implementation but agree to return something that fulfills the given interface. If you want to conceed to even less obligations, you could return the interface Iteratable instead of List.
Checkout the Java API, you will find standard classes like ArrayList implement many interfaces. You could always use an ArrayList internally and return it as the smallest interface possible to do the job.
Back to your project. It would be essential to refer to the Registry (ListAdministrator) via its interface, not its concrete class. The interface would define methods like
interface IndexCardRegistry {
void delete(Long id) throws IllegalAccessException;
void update(Long id, Some data) throws IllegalAccessException;
// ...
}
What it does is of no concern for the client, it just hopes everything goes right. So if a client calls the repositories update method it would rely on the repository to update the targeted IndexCard. The repository could store the data as it wants, in a HashMap, in a List or even in a database, it would not matter to the clients.
class IndexCardMapBasedRegistry implements IndexCardRegistry {
private Map store = new HashMap();
void delete(Long id) throws IllegalAccessException {
// code to remove the IndexCard with id from the hashmap
}
void update(Long id, Some data) throws IllegalAccessException {
// code to get the IndexCard with id from
// the hashmap and update its contents
}
// ...
}
Now the new iteration, at creation of your registry you swap out IndexCardMapBasedRegistry for the new
class IndexCardDatabaseRegistry implements IndexCardRegistry {
private Database db;
void delete(Long id) throws IllegalAccessException {
// code to remove the IndexCard with id from the database
}
void update(Long id, Some data) throws IllegalAccessException {
// code to update the IndexCard with id in the database
}
// ...
}
IndexCardRegistry indexCards = new IndexCardMapBasedRegistry(); becomes
IndexCardRegistry indexCards = new IndexCardDatabaseRegistry();
The client must not change at all, but the Registry would be able to handle an amount of IndexCards that otherwise would blow your computers memory.
Stay with IndexCard class and dont need to create new class ListAdministrator
In class IndexCard you have list as of type hashmap and it represent in memory data structure and you have n number of method in this class to work in this data structure so i suggest stay with single class as it will serve single responsibility.
I just heard of AspectJ and it doesn't look too easy to understand, so I want to know beforehand if it (or anything else) will help me with my problem or not.
I have bunch of simple POJO classes and want to write binary serializers for them but without writing Write/Read methods by hand for each class. I could've done so with help of reflection but that will affect runtime performance. I believe I need something similar to Macroses in Scala with compile-time reflection and quasiquotes.
Update:
I'm unable to use any serialization available, because I have custom binary protocol which I can't modify (online game)
Update 2:
Example POJO with it's read, write and some helper methods. Not final version, there possibly could be some annotations, for example, but general structure should be the same. I also omitted inheritance for simplicity, in reality LoginPacket extends CommandPacket class which in turn extends Packet class.
public class LoginPacket {
public short length;
public int sessionId;
public short command;
public short error;
public String reason;
private String getString(ByteBuffer data) {
short length = data.getShort();
byte[] stringData = new byte[length];
data.get(stringData);
return new String(stringData, "UTF-8");
}
private void putString(ByteBuffer data, String someString) {
data.putShort(someString.length());
byte[] stringData = someString.getBytes("UTF-8");
data.put(stringData);
}
public static LoginPacket read(ByteBuffer data) {
LoginPacker loginPacket = new LoginPacket();
loginPacket.length = data.getShort();
loginPacket.sessionId = data.getInt();
loginPacket.command = data.getShort();
loginPacket.error = data.getShort();
loginPacket.reason = getString(data);
return loginPacket;
}
public void write(ByteBuffer data) {
data.putShort(this.length);
data.putInt(this.sessionId);
data.putShort(this.command);
data.putShort(this.error);
putString(data, this.reason);
}
}
I don't think you need to use AspectJ to modify your classes. I don't see what benefits using compile team weaving would add. I would suggest having your POJOs use implements Serializableand then serialize your objects using an ObjectOutputStream.
A simple example writing an object to a file:
outputStream = new ObjectOutputStream(new FileOutputStream(filePath));
outputStream.writeObject(yourObject);
...
// do whatever else and close stream
Similar questions:
Saving to binary/serialization java
Best way to store data for your game? (Images, maps, and such)