Migration from JDK8 to JDK11 causing java.lang.UnsupportedOperationException - java

You you can see from the class name properties.stringPropertyNames() returns an Collections$UnmodifiableCollection. Unmodifiable means you can't add, insert, remove or change something on this collection

Now that you have explained what the type of properties is java.util.Properties the answer is clear. In Java 8, Properties.stringPropertyNames() returned a set whose modifiability was unspecified:
"Returns a set of keys in this property list where the key and its corresponding value are strings, including distinct keys in the default property list if a key of the same name has not already been found from the main properties list. Properties whose key or value is not of type String are omitted."
"The returned set is not backed by the Properties object. Changes to this Properties are not reflected in the set, or vice versa.".
In Java 11, it is specified to be unmodifiable.
"Returns an unmodifiable set of keys from this property list where the key and its corresponding value are strings, including distinct keys in the default property list if a key of the same name has not already been found from the main properties list. Properties whose key or value is not of type String are omitted."
"The returned set is not backed by this Properties object. Changes to this Properties object are not reflected in the returned set."
The change happened in Java 9. This is related to bug 8059361.
(This is was an incompatible change in the sense that it could break customers' code if they relied on being able to modify the returned set. However, that code was relying on unspecified behavior, so you could argue that it was broken already.)

As i understand correctly, you have unmodifiable set and you are tying to change it here
parameterNames.removeIf(s -> !s.startsWith(seq));
that's why you getting this error/exception.
Set<String> parameterNames = new HashSet<>(properties.stringPropertyNames());
This will create a new Set with same content which can be altered.

Related

Replacing Duplicate values inside Set in Java instead of rejecting

I have to insert data inside Set in Java code.
To identify duplicates based on id in entity, I have overridden equals and hashcode method.
Now, the values with duplicate id are rejected when trying to add inside Set.
Present behavior - Set rejects new data with id already existing in Set
Expected: How to make Set replace the new duplicate values with the same id instead of rejecting? [similar to Map which replaces duplicate key ]
Thanks

Error while defining a EEList Type attribute in EMF

In Eclipse, I'm trying to add a List to my EMF Model.
In .ecore model:
I add a new class "MyClass" to my model in EMF
then add an attribute "MyList" to this class, set the EType of this attribute as EEList<>
then set the dataType of the list element to EString.
But when i try to open the genmodel of this model, appears an error saying:
"The attribute 'MyClass.MyList' is not transient so it must have a data type that is serializable".
What am i doing wrong?
Thanks in advance.
You do not have to 'manually' deal with it being a list.
Remember, you are using UML.
A List is merely an ordered association to a type, in which the upper bound is set to *.
Therefore, simply add MyList to MyClass, set its multiplicity to 0..-1 (by setting its upper bound to -1, which means * in EMF) and ensure the association's Ordered property is set to True (otherwise you would get a Set). Also set its type to EString.
Here is an example, in which a DFA has a list of the type State, in accordance with the above instructions. I also set "containment" to true, as to make the list hold a strong reference the objects it contains (this has to do with memory management, I would suggest you to do the same). Note that I've set the type to State, as this is a list of State objects.

Are Java system properties always non-null?

There are a couple of Java system properties, among them things like java.home and path.separator, user.home. The spec does not mention any formal promises on the existence of those values.
Especially I am interested in user.home. Does it always point to some existing path?
I think you can safely assume that all the properties in that list is always available in any recent (Oracle-provided) JVM.
However, a null check is more defensive, and not expensive in this case.
I've never seen user.home to be null or be incorrectly specified by default. However, keep in mind that users can override with -Duser.home=..., so you can't rely on it to point to an existing path.
The documentation you pointed out states
The getProperty method returns a string containing the value of the property. If the property does not exist, this version of getProperty returns null.
So if the property does not exist you get a null value
The spec says that user.home contains user home directory, it does not say it may contain null. I have no doubt that JVM guarantees that it is always set.
The default properties will differ depending on OS. There will be some keys for which no values are defined. On my machine I found user.variant and user.timezone without any values! Following is the code which will list down all the key value pairs:
Properties prop = System.getProperties();
Set<Object> set = prop.keySet();
Iterator<Object> itr = set.iterator();
while(itr.hasNext()){
Object obj = itr.next();
String propVal = System.getProperty(obj.toString());
System.out.println(obj.toString()+" = "+propVal);
}
}
Regarding your specific reference about user.home, it seems it defined most of the time. Check out this interesting post where people have posted the list of system properties on different machines.

Difference between "get' VS "getProperty"

Properties myProp = new Properties();
myProp.put("material", "steel");
Properties prop1 = new Properties(myProp);
System.out.println(prop1.get("material") + ", " + prop1.getProperty("material"));
// outputs "null, steel"
Isn't get similar to getProperty in the sense that it returns the entries/attributes of
an Object? Why is it not returning 'steel' when using get?
get is inherited from Hashtable, and is declared to return Object.
getProperty is introduced by Properties, and is declared to return String.
Note thatgetProperty will consult the "defaults" properties which you can pass into the constructor for Properties; get won't. In most cases they'll return the same value though. In the example you've given, you are using a default backing properties:
prop1 doesn't directly contain an entry for "material", hence why get is returning null.
myProp does contain an entry for "material", so when you call prop1.getProperty("material"), it will find that it doesn't have it directly, and check in myProp instead, and find "steel" there.
A look at the docs shows that get is inherited, and returns Object whereas getProperty is a member of Properties and returns the String.
Seemingly they should return the same, however from the docs again:
If the key is not found in this property list, the default property list, and its defaults, recursively, are then checked.
So it is best to use getProperty as it will return the default if it is not found.
Your second Properties object (props or prop1?), has no properties added directly to it. It only uses myProp as defaults. So those values never get added to the backing HashMap. Properties.getProperty() doesn't find "material" in the backing HashMap so it can look in the defaults. But the inherited HashMap.get() only looks in the backing HashMap and not in the defaults that you passed into the constructor.

Empty list in App Engine Datastore: Java vs Python

I have the following java model class in App Engine:
public class Xyz ... {
#Persistent
private Set<Long> uvw;
}
When saving an object Xyz with an empty set uvw in Java, I get a "null" field (as listed in the appengine datastore viewer).
When I try to load the same object in Python (through remote_api), as defined by the following python model class:
class Xyz(db.Model):
uvw = db.ListProperty(int)
I get a "BadValueError: Property uvw is required".
When saving another object of the same class in Python with an empty uvw list, the Datastore viewer prints a "missing" field.
Apparently empty lists storage handling differs between Java and Python and lead to "incompatible" objects.
Thus my question: Is there a way to, either:
force Java to store an empty list as a "missing" field,
force Python to gracefully accept a "null" list as an empty list when loading the object?
Or any other suggestion on how to handle empty list field in both languages.
Thanks for your answers!
It should work if you assign a default value to your Python property:
uvw = db.ListProperty(int, default=[])
I use the low-level java api, so perhaps what I am doing would be different. But before I save a collection-type data structure to the datastore, I convert it into something that the datastore naturally handles. This would include mainly Strings and ByteArrays.
It sounds like java app engine is interpreting the empty set as a null value. And python is not reading this null value correctly. You might try saving an empty set as the String value "empty set". And then have python check to see if the datastore holds that string value. If it does, it could allocate a new empty set, if not, it could read the property as a set.
The Java Set behavior is because Java's Collections are reference types, which default to being null.
To actually create an empty Set, declare it like this:
#Persistent
private Set<Long> uvw = new HashSet<Long>();
or using some other implementation of Set on the right side. HashSet is the most commonly used Set type, though. Other interesting set types are the two thread-safe Sets CopyOnWriteArraySet and ConcurrentSkipListSet; also the Ordered Set type LinkedHashSet and the Sorted Set type TreeSet.
It may work to you
uvw = db.ListProperty(int, default=[])
Its the most comment way to short it out...

Categories

Resources