I'm currently trying to test the UI of an Eclipse RCP application. When executed manually, the application starts fine and can be used correctly. However, when QF-Test launches the application, I get a ClassCastException in a 3pp module:
java.lang.ClassCastException: java.io.File cannot be cast to java.lang.String
at com.solarmetric.conf.ConfigurationImpl.fromProperties(ConfigurationImpl.java:560)
at com.solarmetric.conf.ConfigurationImpl.loadDefaults(ConfigurationImpl.java:186)
After analyzing the code of the 3pp library I see that the exception occurs when trying to cast a System's property value to a String. This shouldn't be a problem because all properties values should be String (see this answer). However, QF-Test is adding 3 properties which their values are File (java.io.File) objects. More precisely:
jython.home = C:\Program Files\qfs\qftest\qftest-4.2.0\jython
groovy.home = C:\Program Files\qfs\qftest\qftest-4.2.0\groovy
javascript.home = C:\Program Files\qfs\qftest\qftest-4.2.0\javascript
I would like to remove those wrong property values. I've already tried to define them manually as parameters of the QF-Test command line call without success.
Some help would be very appreciated.
This behaviour of QF-Test was fixed with QF-Test 4.2.1 (released February 26, 2018), see https://www.qfs.de/en/qf-test-manual/lc/manual-en-history.html#sec_N1D715:
Bug fixed:
In a few cases a broken system property set by QF-Test could interfere with SUT startup.
So the answer is to simply update your QF-Test!
Unfortunately, I do not know a fix for QF-Test.
If possible, I recommend the workaround to correct the properties before use.
Properties sysProps = System.getProperties();
Properties copyProps = new Properties();
synchronized (sysProps) {
copyProps.putAll(sysProps);
}
Set<Entry<Object, Object>> entrySet = copyProps.entrySet();
for (Entry<Object, Object> entry : entrySet) {
if (!(entry.getKey() instanceof String) || !(entry.getValue() instanceof String)) {
sysProps.remove(entry.getKey());
sysProps.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
}
}
Related
On a windows 2012 R2 platform I noticed that winver returns 6.3, but System.getProperty("os.version") returns 6.2 ; I am looking at this source code :
class [More ...] Properties extends Hashtable<Object,Object> {
protected Properties defaults;
public String [More ...] getProperty(String key) {
Object oval = super.get(key);
String sval = (oval instanceof String) ? (String)oval : null;
return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
}
}
I am suspecting the value of os.version is obtained from here. Is my suspicion right ?
Object oval = super.get(key);
What would be the contents of the HashTable and how is this populated ? ( I have not loaded the java source code as a project into my eclipse work-bench)
The system property os.version is added by the JVM itself thanks to the static native method initProperties(Properties props) as you can see here at the line 527. This method is called while initializing the System class which is done by the method initializeSystemClass().
In other words it means that the native code of your JVM is not able to recognize your os version, you should upgrade your JDK to fix this issue.
Here is a blog post where the blogger had the same issue with an old version of Java, upgrading it was enough to fix the issue.
This problem was seen before java 6u38. From 6u38, this issue is solved. The security baselines for the Java Runtime Environment (JRE) at the time of the release of JDK 6u38 are specified.
First using the EPM Java JDK version.
As you see it is generating incorrect information, now using a later JDK 7 release.
So this highlights it is the down to the version of Java which is causing the issue.
Resource Link:
EPM 11.1.2.4 - Java versions and why Windows Server 2012 is not
correctly recognised
I am suspecting the value of os.version is obtained from Object oval =
super.get(key);. Is my suspicion right ?
Answer:
You are right. But here is some mechanism
First mechanism:
System.getProperty("os.version"); //which is called the OS version.
The getProperty method returns a string containing the value of the property. If the property does not exist, this version of getProperty returns null.
Second Mechanism:
System.getProperty("os.version", "Windows Server 2012 R2(6.3)");
getProperty requires two String arguments: the first argument is the key to look up and the second argument is a default value to return if the key cannot be found or if it has no value. For example, the following invocation of getProperty looks up the System property called os.version. This is not a valid system property, so instead of returning null, this method returns the default value provided as a second argument: "Windows Server 2012 R2(6.3)"
The last method provided by the System class to access property values is the getProperties method, which returns a Properties object. This object contains a complete set of system property definitions.
What would be the contents of the HashTable and how is this populated
?
Answer:
Properties extends java.util.Hashtable. Some of the methods inherited from Hashtable support the following actions:
testing to see if a particular key or value is in the Properties
object,
getting the current number of key/value pairs,
removing a key and its value,
adding a key/value pair to the Properties list,
enumerating over the values or the keys,
retrieving a value by its key, and
finding out if the Properties object is empty.
You can learn more from here about System Properties and Properties
Property related info is read and can be changed through this java class: PropertiesTest.java
Note and Recommendation from Oracle
Warning: Changing system properties is potentially dangerous and
should be done with discretion. Many system properties are not reread
after start-up and are there for informational purposes. Changing some
properties may have unexpected side-effects.
Note: Some of the methods described above are defined in Hashtable,
and thus accept key and value argument types other than String. Always
use Strings for keys and values, even if the method allows other
types. Also do not invoke Hashtable.set or Hastable.setAll on
Properties objects; always use Properties.setProperty.
I thought this would be a very simple thing. So far however I'm unable to access the String for my gradle job's Java.Home, the official name:
For example, see: org.gradle.java.home
Apparently I can set this value with gradle.properties settings file. I've done that and the gradle output confirms this.
For all that, none of these print statements work...
print "org.gradle.java.home = $org.gradle.java.home"
print "org.gradle.java.home = "+ project.properties['org.gradle.java.home']
print "org.gradle.java.home = $gradle.java.home"
print "${project.property('org.gradle.java.home')}"
Looking at back at this question, I would have thought one of the options tried would yield a result.
How can I access system level properties?
Only two options may work:
print "org.gradle.java.home = "+ project.properties['org.gradle.java.home']
print "${project.property('org.gradle.java.home')}"
and the second will fail since there's no checking if such property exists. Gradle throws an exception on access to non-existing property.
The last two will not work because there's no property org and gradle objects has no java property - more explanation can be found here - you need to understand how string interpolation works with groovy.
And finally, these properties are used to pass arguments to gradle. So the following will work:
print "org.gradle.java.home = "+
project.properties['org.gradle.java.home']
run with:
gradle -Dorg.gradle.java.home=random_dir
With some trial-and-much-error, I have found that one may print the java.home property on Windows with Gradle 2.4; when ...
Use your gradle.properties file, e.g.
For example
compile.options.fork = true
org.gradle.daemon = true
org.gradle.java.home = b:/lang/java/jdk/v1.8u45
The same settings in GRADLE_OPTS had no effect. The print command used, is:
print "org.gradle.java.home = "+ "${project.property('org.gradle.java.home')}"
I believe the compile.options.fork is also required. It had no effect before when I was using GRADLE_OPTS. Although the Gradle message to use fork is quite clear on the matter.
see also:
- https://docs.gradle.org/2.4/userguide/gradle_daemon.html
I have used EMC Documentum Foundation Classes to perform some actions in documentum repository. The code was working fine. I exported the project as a runnable JAR and then tried to run it. However I got following error and I am not able to understand it.
And here is the code for DocMovementHandler.getSession()
Actually this is no new code but regular code for obtaining documentum session
public IDfSession getSession(String userName, String password)
{
DfClientX clientx = null;
IDfClient client = null;
IDfSession session = null;
try {
// create a client object using a factory method in DfClientX
clientx = new DfClientX();
client = clientx.getLocalClient(); //takes time
// call a factory method to create the session manager
IDfSessionManager sessionMgr = client.newSessionManager();
// create an IDfLoginInfo object and set its fields
IDfLoginInfo loginInfo = clientx.getLoginInfo();
loginInfo.setUser(userName);
loginInfo.setPassword(password);
// set single identity for all docbases
sessionMgr.setIdentity("xyz_repo", loginInfo);
session = sessionMgr.getSession("xyz_repo"); //takes time
//sessionMgr.beginTransaction();
System.out.println("Session obtaied.");
}
catch (DfServiceException dse)
{
DfLogger.debug(this, "Error while beginning transaction. ", null, dse);
dse.printStackTrace();
}
catch (Exception e)
{
DfLogger.debug(this, "Error while creating a new session. ", null, e);
e.printStackTrace();
}
return session;
}
And that line 38 is client = clientx.getLocalClient();
InvocationTargetException is a wrapper. It says, "an exception occurred behind this reflection call", and you use getCause() to get at the inner exception.
The stack trace contains the inner exception. It's an ExceptionInInitializerError. That's another wrapper. It says, "whatever you did caused a new class to be loaded, and that class's static initializer threw an exception".
The final exception in this chain is the NullPointerException. That's the one you need to solve. Which means you need to debug this com.documentum thing. As the comments pointed out, that's not going to be easy.
Here is the most likely problem:
The static initializer in one of the classes whose names you have struck is adding an entry with either a null key or a null value to a Hashtable, which does not allow null keys or values.
It is using the Hashtable as a place to store a bunch of persistent properties and all that, and my guess is that the value for one of the entries was the null (which is a perfectly reasonable way to indicate that some feature is unavailable or something like that).
The now deprecated Hashtable needs to be replaced with the more modern HashMap.
If it is a library, that you can't just modify, you should replace the whole library with an updated version.
Here are some clues may be helpful.
The NullPointerException is thrown by Hashtable#put, and this is normally because either the key or the value is null.
Hashtable#put is called by PreferenceManager.readPersistenceProperties, so most likely it's because something is missing in a properties file so the value is null.
This NPE caused the DfClient class could not be loaded.
DfPreferences is the class loading the DFC configuration file dfc.properties. There must be something wrong with it.
Ohkay I did not pin pointed the root cause, but found the solution that will definitely work everytime.
EMC provides a flavor of Eclipse called Documentum Composer to work with Documentum Projects. Since Eclipse variation we can create other types of projects like normal Java project, dynamic web project, web services in this. So I recreated my project in Documetnum Composer and exported it as JAR and whoaaaa it worked.
I tried this many times and this worked all time.
Some points to note:
You have to replace dfc.properties file in Composer installation folder with one in Content Server
The Export to JAR wizard in Composer is a bit different than one in Eclipse
This is usually caused by dfc.properties being incorrect.
Preferences are stored on the global registry repository and the connection details should be specified in dfc.properties. If not, this (or a similar error can occur).
Also, always try to clear cache and use the correct version of the dfc jar's (v6.7 content server requires 6.7 jars, etc...).
steps I do:
I do in code
System.setProperty("myproperty", 1);
and then I set in a shell script the property "myProperty" to 3.
like this:
# setprop "myproperty" 3
and then in the code I try to read the property like this:
System.getProperty("myproperty");
I get the value of 1. which means that the set from the shell didn't actually work.
but when I print all props from shell with
# getprop
I see in the list that myproperty equals 3.
in shorter words: I want to change the value of a property from a script, and I see that this scripts actually changes the property but in the java code I get the old value.
any ideas?
Java code in Android provides System.getProperty and System.setProperty functions in java library but it's important to note that although these java APIs are semantically equal to native version, java version store data in a totally different place. Actually, a hashtable is employed by dalvik VM to store properties. So, java properties are separated, it can't get or set native properties, and neither vice versa.
You can use android.os.SystemProperties class can manipulate native properties, though it's intended for internal usage only. It calls through jni into native property library to get/set properties.
getprop/setprop work on android.os.SystemProperties, not on java.lang.System.
Unfortunately, this class is not available to third party application. Apparently you have rooted your device, so you may still access it.
You can use that snippet to run getProp as shell command and get the value of any property:
private String getSystemProperty(String propertyName) {
String propertyValue = "[UNKNOWN]";
try {
Process getPropProcess = Runtime.getRuntime().exec("getprop " + propertyName);
BufferedReader osRes =
new BufferedReader(new InputStreamReader(getPropProcess.getInputStream()));
propertyValue = osRes.readLine();
osRes.close();
} catch (Exception e) {
// Do nothing - can't get property value
}
return propertyValue;
}
Is it possible to initialize Java system properties using some sort of configuration file?
(ie: can you set java.library.path using a file inside your jar)
EDIT: Clarification: I am asking specifically about initializing the system properties to a value in a file, not setting them later from inside the virtual machine. Yes, you can change system properties to whatever you want very easily after the machine starts up, but the Java system classes will not use the new values.
Practically speaking, this means System.setProperty and System.setProperties are useless for loading native libraries, as JNI will always use the original value of java.library.path to load libraries with. I'm trying to figure out if there's a cleaner alternative to just putting -Djava.library.path=whatever in start up scripts everywhere.
There is a way to set java.library.path programatically, see this.
The code is a hack to set the sys_path field on the ClassLoader,
System.setProperty( "java.library.path", "/path/to/libs" );
Field fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" );
fieldSysPath.setAccessible( true );
fieldSysPath.set( null, null );
It would be pretty simple to do yourself:
public static void main(String[] args) {
Properties p = new Properties();
p.load(...); // Load the properties from a file in your jar
for (String name : p.stringPropertyNames()) {
String value = p.getProperty(name);
System.setProperty(name, value);
}
}
Use JAVA_TOOL_OPTIONS environment variable. _JAVA_OPTIONS may also work, but it's not documented at all. The JAVA_TOOL_OPTIONS is weakly documented, but here are some links:
http://www.oracle.com/technetwork/java/javase/envvars-138887.html#gbmsy
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/envvars002.html
https://bugs.openjdk.java.net/browse/JDK-4971166
An example of use:
set JAVA_TOOL_OPTIONS=-Dmy.property=sth
When launching JVM you should see a message:
Picked up JAVA_TOOL_OPTIONS: ...
You cannot initialize them as far as I know, but you can definitely override their values to anything you want, using any source you wish.
I think the reason why System.setProperty(key,value) is useless for java.library.path in your program is your application is started, you need set it before your program is running.
Check your native library, if the library have any dependency that not included in the java.library.path, System.load will fail, as if System.setProperty(key, value) does not work as expected.
You can parse properties file with additional code (another instance of JVM), redirect its output to var and use this variable as parameter to your java invocation. For example:
public class SystemPropertyLoader {
public static void main(String[] args) throws Exception {
String file = args[0];//TODO check args
Properties properties = new Properties();
InputStream is = new FileInputStream(file);
properties.load(is);
is.close();
StringBuilder builder = new StringBuilder();
for (Entry e : properties.entrySet()){
builder.append("-D");
builder.append(e.getKey());
builder.append('=');
builder.append(e.getValue());
builder.append(' ');
}
System.out.println(builder.toString());
}
}
and
#!/bin/ksh
properties_variable=$(java SystemPropertyLoader input.properties)