ClassCastException: java.lang.Object incompatible with com.company.base.BaseDocument - java

I have a piece of code that has to be JDK 1.4 compliant. And below is a snippet which gets a runtime exception.
BaseDocument baseDocument = new BaseDocument();
baseDocument.setGuid("{somethinghere}");
List document = new ArrayList();
document.add(baseDocument);//runtime error
Exception:
java.lang.ClassCastException: [Ljava.lang.Object; incompatible with [Lcom.company.base.BaseDocument;
I don't understand why we cant cast it to a java Object(since Object is the parent class of all Classes in java).
Im using IBM JDK version 1.7 with Eclipse compiler settings set to JDK 1.4
Please explain what mistake I'm doing here. I know generics is the standard, but it has to be JDK 1.4 compliant :(
Thanks in advance!

Actually, the message says:
[Ljava.lang.Object; incompatible with [Lcom.company.base.BaseDocument;
The [ characters are very important. Apparently, something is attempting cast something of type Object[] to BaseDocument[]; i.e. you are dealing with array types here.
However, I have no idea what is actually causing the problem here, because (on the face of it) there should be no instances of BaseDocument[] in the code you have posted. Furthermore, I don't believe your claim that that exception is thrown at that line. Here is the source code of the ArrayList.add method (Java 6 version):
private transient Object[] elementData;
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
An assignment of a reference into an object array (Object[]) does not entail any runtime type-checks, and cannot throw a ClassCastException.
If you showed us a complete stacktrace, it would be easier to diagnose.

Related

Writing forwards-compatible code when an API introduces a new exception type

One problem I've noticed when porting reflection code from Java 8 to Java 9+ is that setAccessible() now throws InaccessibleObjectException in addition to SecurityException when before in Java 8 InaccessibleObjectException wasn't an exception type.
What is the accepted way to write code that has to catch and handle an exception that it can't know about since it's in a future Java version yet still be compatible with the current version? (In this case the only ancestor class is RuntimeException, but that feels like a smell to me personally to write such an all-encompassing catch.)
You could ask the runtime for the Java version (as described in this post) and use exception.getClass().getName() to get the exception class name in a backward-compatible way
In other words
try {
method.setAccessible();
} catch (RuntimeException e) {
String version = (System.getProperty("java.version"))
String minorVersion = ver.split("\\.")[1];
if (minorVersion >=9) {
if (e.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
// Handle java 9 reflection access issue
} else {
// Handle java 8 runtime exception
}
}

How to avoid java.lang.NoSuchMethodError on earlier java versions

I got the following error today:
java.lang.NoSuchMethodError: javax.swing.JList.getSelectedValuesList()Ljava/util/List;
We have some customers still using old java6 versions out there. (Some old posready/embedded-version of windows that doesn't accept installing 1.8 directly..)
Therefore I use compiler compliance level 1.6 in eclipse. However, after an upgrade of our software, some customers reported errors/freezing. I logged in, and found the following error:
java.lang.NoSuchMethodError: getSelectedValuesList()Ljava/util/List;
It appears that this particular JList method in was introduced in 1.7, and I have started using it since getSelectedValues() is deprecated.
But this breaks things on 1.6, since the method does not exist in 1.6.
I have made a workaround, instead of calling getSelectedValuesList() I now call the following method:
public static <E> java.util.List<E> getSelectedValuesList(javax.swing.JList<E> l) {
try {
return l.getSelectedValuesList();
}catch(java.lang.NoSuchMethodError err) {
ArrayList<E> v = new ArrayList<E>();
Object[] oo = l.getSelectedValues();
for (Object o : oo) {
v.add((E)o);
}
return v;
}
}
This seems to work ok. But my question is, since source level is 1.6, how do I detect similar errors? Since I don't even have 1.6 installed, how can I know for sure that all my swing methods that I call actually works in 1.6? I don't want to introduce yet another bug later on. :-)

AbstractMethodError on Node.getTextContent()

Below is the sample code block throwing AbstractMethodError:
import org.w3c.dom.Node;
..
Node root = soapBody.getElementByTagNameNS("http://xxx.xxx/Schema/v9", "Result").item(0); //Namespace
for (int i = 0; i < root.getChildNodes().getLength(); i++) {
Node child = root.getChildNodes().item(i); //Set to SubResult
String result = child.getTextContent(); //Throws error
}
The sample soap response :
soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header/><soapenv:Body><a1:Response xmlns:a1="http://xxx.xxx/Schema/v9"><a1:SubResult>50</<a1:SubResult></a1:Response></soapenv:Body></soapenv:Envelope>
Error thrown:
java.lang.AbstractMethodError: org.apache.axis.message.MessageElement.getTextContent()Ljava/lang/String;
Java version used : 1.5
Tomcat Version - 6.0.41
Checked org.w3c.dom.Node for 1.5 and it does have the method getTextContent()
What could be the possible reason for this error?
Also, why does this appear : org.apache.axis.message.MessageElement instead of org.w3c.Node?
The javadoc of the AbstractMethodError says:
Thrown when an application tries to call an abstract method. Normally,
this error is caught by the compiler; this error can only occur at run
time if the definition of some class has incompatibly changed since
the currently executing method was last compiled.
So it looks like you have some incompatible versions of something in your classpath.
org.apache.axis.message.MessageElement is part of Axis and should implement org.w3c.dom.Node so the versions of those two don't seem to match. Make sure you have matching versions of the two in your classpath.

Incoparable Java Types boolean and object

I have this piece of code which worked in Java 6
if(false==sess.getAttribute("admin") || null==sess.getAttribute("admin"))
{
res.sendRedirect("/myapp/login.jsp?errmsg=You must log in as an administrator to manage resources");
return;
}
I want to familiarize myself with the new features of Java 7 and what it offers new in javaee hence I upgraded netbeans to 7.4 and jdk 7u45.
My project opened successfully however the file with this code is marked as a java class with an error by netbeans. Running the project I get the error
java.lang.RuntimeException: Uncompilable source code - incomparable types: boolean and java.lang.Object
What I want to ask is why this worked in java6 and doesn't work in java7
FYI HttpSession sess = req.getSession();
HttpSession.getAttribute returns an Object.
Change the line to (Boolean.FALSE==sess.getAtrribute)
Looks like autoboxing (boolean to Boolean) has changed in Java.
Unfortunately I cannot reproduce your error. I have seen a similar error message in the same Netbeans 7.4/jdk 7u45.
My code:
if (true == evt.getNewValue())
(where evt is a PropertyChangeEvent)
The message in Netbeans (when I hover over the red cross left to the statement) says "incomparable types: boolean and Object". Notice the difference with your message: the missing "java/lang" before Object.
And even stranger: my code compiles without any problem.
Compiler options in Netbeans are: "-version -Xlint:unchecked -Xlint:deprecation"
You should try with
if(false==(Boolean)sess.getAttribute("admin") || null==sess.getAttribute("admin"))
{
res.sendRedirect("/myapp/login.jsp?errmsg=You must log in as an administrator to manage resources");
return;
}
getAttribute probably returns either an Object or a boolean. If it returns a boolean, then null==getAttrubute will not work and if it returns an Object then false==getAttribute will fail.

Find exception thrown by 3rd party library

I hope I can explain this correctly. I am using the Javolution library to do reading and writing of an XML config file. I'm using XMLStreamReader/Writer. During reading, I'm looking to read a tag and store its attributes in a LinkedHashMap. However, I'm having an exception being thrown, that to me looks to make no sense due to when it's thrown and what's currently going on in the code.
Using the Eclipse debugger, the exception is being thrown when an attribute's key and value is being added to my map.
public class Element {
private HashMap<String, String> attributes = new LinkedHashMap<String, String>();
...
public void setAttribute(String key, String value) {
...
attributes.put(key, value);
}
}
Straight after the key and value are added, this catches an exception from Javolution:
javolution.xml.stream.XMLStreamException: Local name cannot be null
Neither key or value are null. When they are being added to the map, I cannot step into the code further to see where the exception is being thrown, there is no stack trace, no file/line number shown anywhere to explain where or even how the exception is thrown.
From a quick google search of older implementation of Javolution, I can see that this particular exception is only thrown using a few methods of the XMLStreamWriterImpl type. I've set breakpoints at each use I have of these methods, but the debugger doesn't catch them being used until much later in the code (and my localName variable is initialised at declaration).
Would anyone have any advice for how I could determine why this exception is being thrown?
Stack Trace:
Java HotSpot(TM) 64-Bit Server VM[localhost:3999]
Thread [main] (Suspended)
XMLImplMain$Element.setAttribute(String, String) line: 827
XMLImplMain.translate(Element) line: 133
XMLImplMain.translate(Element) line: 140
XMLImplMain.translate(Element) line: 140
XMLImplMain.loadXML(String) line: 118
Bootstrap.main(String[]) line: 32
Thread [EventWriter] (Running)
It's possible that this Javolution library is not correctly compiled, without the argument -g when compiling via javac perhaps and this will make the output jar lack of debug information. You can find the corresponding source code of the jar you currently working on, and recompile it with sufficient arguments to make it debugable by yourself.
Or, there is a workaround which is way more complicated but no customizing compilation is needed, writing a BTrace script and catch the initialization of all the XMLStreamException and then print out the stacktrace, like this:
package com.sun.btrace.samples;
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
#BTrace
public class OnThrow {
#OnMethod(clazz = "javolution.xml.stream.XMLStreamException", method = "<init>", location = #Location(Kind.RETURN))
public static void endMethod(#Self Exception self) {
jstack();
}
}
and there is similar example here. You can dig a little deeper here.

Categories