Using an unsupported library, leading me onto casting - java

I have to work with this library that deals with a standard for biodiversity. Essentially, it reads in csv, xml etc and validates it, allowing one to iterate through the records with the type DarwinCoreRecord
For some odd reason, as soon as the object is moved from the iterator, it is gone. Small example below:
ArrayList<DarwinCoreRecord> dwc = new ArrayList<DarwinCoreRecord>();
for(; iter.hasNext();) {
DarwinCoreRecord record = iter.next();
System.out.println(record.getSomeValue());
dwc.add(record);
}
That print statement is perfect and prints out the right details, if I out that print statement outside of the for loop, nulls are had by all.
So, onto my question (unless anyone can solve the above). I created a skeleton class that extends this DarwinCoreRecord. It looks exactly like this:
public class DWCRecordStore extends DarwinCoreRecord {
public DWCRecordStore() {
}
}
This was just to test my plan would work but I am getting a classcastexception. It has been a while since I have dealt with casting (in Java, at least) but I see no issues. I am not casting from DWCRecordStore to DarwinCoreRecord so I cannot see the problem.
Does anyone see anything glaring that I have missed?
Thanks in advance.
EDIT: Sorry, error is here:
java.lang.ClassCastException: org.gbif.dwc.record.DarwinCoreRecord cannot be cast to com.encima.DWCRecordStore
at com.encima.DroolsTest.main(DroolsTest.java:37)
EDIT 2: Added my use of the casting.
DWCRecordStore drs = new DWCRecordStore();
DarwinCoreRecord dwc = iter.next();
drs = (DWCRecordStore) dwc;

You are trying to cast DarwinCoreRecord into an DWCRecordStore - but the first is not an instance of the second!
Think of DarwinCoreRecord as a polygon and DWCRecordStore as a square, you can always cast a square (DWCRecordStore) to a polygon (DarwinCoreRecord) - but not the other way around.
It might be that you are trying to store an object that was returned from the lobrary as a DWCRecordStore. But the library is unfamiliar with DWCRecordStore, it returns only DarwinCoreRecord objects, which are not DWCRecordStore.
Pinpointing the exact problem might require more code - how exactly did you use your new class.
EDIT: your last edit clarifies it, since dwc is not instance of DWCRecordStore, it cannot be casted to one.
An alternative might be creating a constructor: DWCRecordStore(DarwinCoreRecord), and using:
drs = new DWCRecordStore(dwc);

Related

How to get protected value out of one class and into another

I have two public classes, VAG.java and XY.java. Inside VAG there's a protected value I would very much like, nay, I need to have in XY. All attempts thus far have failed. From inside XY
List<Double> val = VAG.valOfConcern;
yields java.lang.NullPointerException, calling
public List<Double> getVal( ) {
return valOfConcern;
}
on my VAG object yields the same. Now I know what you're thinking; spoof, it's because the object is null, has it been initialized? It has, but maybe that particular variable hasn't been initialized yet? I'm not sure how to ask for help without just posting both full files (~1500 lines) and who's going to want to look through that anyway?
I need a wormhole, is there such a thing? Some hacky way where I can pull off some shared memory type thing in Java? I'm at my wits end, I'm about to start writing the value to a '.txt' and reading it off.
Thank you for listening to me ramble, feel free to tear me a new one, I'm frustrated.

How to fix ClassNotLoaded exception Java [duplicate]

So I'm (remotely) debugging a java/jboss application in Eclipse, stepping through line by line. At one point, an array of GridSquare objects (GridSquare is a fairly simple, standalone class, contains a few properties and methods) is created by a method call, i.e:
GridSquare[] squares = this.theGrid.getSquares(14, 18, 220, 222);
...While when I actually execute the code, the squares array does get populated with GridSquare objects, I get something odd when stepping through the code and debugging. At a breakpoint on the line immediately following the assignment shown above, if I try to view the squares array, instead of a value I get this:
org.eclipse.debug.core.DebugException: com.sun.jdi.ClassNotLoadedException: Type has not been loaded occurred while retrieving component type of array.
...Anyone know what that's about?
Basically it means the class loader has not loaded the GridSquare[] class. That being said it sounds like a bug in the debugger in some way. The breakpoint association with the code seems to be slightly broken. Either you need to recompile to get the line numbers in sync or some other issue is going on. At that point in the code (after the assignment) it needs to be loaded. Unless getSquares actually returns a subclass (GridSquareSubclass[]) at which point the JVM may not have loaded it because it doesn't need it (yet).
I ran into this error because I was running a unit test on code that uses reflection. I had made a special class for testing all the features of the code. Junit apparently uses a separate classloader for test classes (which makes perfect sense) so my code was not able to use reflection on that class. The stack trace I got was extremely generic (java.lang.InstantiationException) but when I checked in debug mode there was more detail on the Exception object itself (org.eclipse.debug.core.DebugException: com.sun.jdi.ClassNotLoadedException) which led me to this conclusion.
So I moved the special class to the main classloader (by moving the file from src/test/java to src/main/java) and it worked fine. I don't like this solution but I cannot figure out an alternative. In my case it's not a big deal but I can see how this might be a concern for others.
I have seen this happen in Eclipse when you have a subclass's class variables hiding a parent class's variables. Somehow that confuses Eclipse (and generally is a bad idea anyway :). For example:
class A {
private String a;
}
class B extends A {
public String a;
}
//Give a SIZE to the array:
GridSquare[] squares = GridSquare[this.theGrid.size()];
//Fill each element of the array with the object constructor to avoid the null value
for(int i=0; i<this.theGrid.size(); i++){
squares[i] = new GridSquare();
squares[i] = this.theGrid.getSquares(14, 18, 220, 222);
}
By initializing GridSquare will solve the problem.
squares =new GridSquare();
I faced the same problem, i just created a public static void main method, created object of same type and Run As java Application, i then removed main method, it now works fine.

Can't get round a ClassCastException

While trying to cast the result of a context.lookup() call in my portal application, I'm getting a ClassCastException for two out of three attempts at casting different results.
After some research I think this: http://wiki.sdn.sap.com/wiki/display/TechTSG/%28AS+Java%29+ClassCastException+Occurs+After+Lookup+Operation holds the answer, but it doesn't explain really how to carry out the two steps.
This code works for fetching the details of an iView, from its path stored in list :
IiView transView1 = (IiView) context.lookup(list.get(i).toString());
but when fetching details of a workset like this:
IPcdContext attrSet = (IPcdContext) context.lookup(list.get(i).toString());
I get a ClassCastException. Any help or explanation as to why I get this error would be greatly appreciated!
edit: This is what the code is based on: http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/6112ecb7-0a01-0010-ef90-941c70c9e401?overridelayout=true
edit2: The object I get back from context.lookup is com.sapportals.portal.pcd.pcm.roles.PortalWorkset which I can't find documentation on.
If context.lookup returns you a PortalWorkset, then there's no way to "get round" the ClassCastException.
Casting does not convert an object to a different class - it's merely a way for you to tell the compiler that you're sure it's a more specific class than its current declared type. In this case, you're saying "I realise that the lookup() method is declared to return Object, but when I call it in this particular context I'm sure that it will always specifically return an IPcdContext object." Your assumption here turned out not to hold, and the program correctly signals this by throwing the exception.
There are potential two causes to your problem:
Your assumption is correct in general, but due to a logic bug you're not passing in the string you expect to the lookup method, and so are getting the wrong thing back altogether. In this case, ensure that the parameter passed to the method is always correct.
Your assumption is incorrect, and you might not always get an IPcdContext back. In this case, you'll need to decide what to do with other objects that are returned, and deal with them appropriately (you can use the instanceof operator to check the class of the returned object).
In any case, whenever you do a cast it's usually beneficial to check that it will succeed first, with an idiom like:
IPcdContext context;
Object obj = context.lookup("foo");
if (obj instanceof IPcdContext) {
context = (IPcdContext)obj;
}
else {
// You got back something else. What to do?
}

Regarding two lines of java code

I am trying to learn a java-based program, but I am pretty new to java. I am quite confusing on the following two lines of java code. I think my confusion comes from the concepts including “class” and “cast”, but just do not know how to analyze.
For this one
XValidatingObjectCorpus<Classified<CharSequence>> corpus
= new XValidatingObjectCorpus<Classified<CharSequence>>(numFolds);
What is <Classified<CharSequence>> used for in terms of Java programming? How to understand its relationships with XValidatingObjectCorpusand corpus
For the second one
LogisticRegressionClassifier<CharSequence> classifier
= LogisticRegressionClassifier.<CharSequence>train(para1, para2, para3)
How to understand the right side of LogisticRegressionClassifier.<CharSequence>train? What is the difference between LogisticRegressionClassifier.<CharSequence>train and LogisticRegressionClassifier<CharSequence> classifier
?
These are called generics. They tell Java to make an instance of the outer class - either XValidatingObjectCorpus or LogisticRegressionClassifier - using the type of the inner object.
Normally, these are used for lists and arrays, such as ArrayList or HashMap.
What is the relationship between XValidatingObjectCorpus and corpus?
corpus is just a name given to the new XValidatingObjectCorpus object that you make with that statement (hence the = new... part).
What does LogisticRegressionClassifier.<CharSequence>train mean?
I have no idea, really. I suggest looking at the API for that (I think this is the right class).
What is the difference between LogisticRegressionClassifier.<CharSequence>train and LogisticRegressionClassifier<CharSequence> classifier?
You can't really compare these two. The one on the left of the = is the object identifier, and the one on the right is the allocator (probably the wrong word, but it is what it does, kind of).
Together, the two define an instance of LogisticRegressionClassifier, saying to create that type of object, call it classifier, and then give it the value returned by the train() method. Again, look at the API to understand it more.
By the way, these look like wretched examples to be learning Java with. Start with something simple, or at least an easier part of the code. It looks like someone had way too much fun with long names (the API has even longer names). Seriously though, I only just got to fully understanding this, and Java was my main language for quite a while (It gets really confusing when you try and do simple things). Anyways, good luck!
public class Sample<T> { // T implies Generic implementation, T can be substituted with any object.
static <T> Sample<T> train(int par1, int par2, int par3){
return new Sample<T>(); // you are calling the Generic method to return Sample object which works with a particular type of generic object, may it be an Integer or a CharSequence. --> see the main method.
}
public static void main(String ... a)
{
int par1 = 0, par2 = 0, par3 = 1;
// Here you are returning Sample object which works with a sequence of characters.
Sample<CharSequence> sample = Sample.<CharSequence>train(par1, par2, par3);
// Here you are returning Sample object which works with Integer values.
Sample<CharSequence> sample1 = Sample.<Integer>train(par1, par2, par3);
}
}
<Classified<CharSequence>> is a generic parameter.
LogisticRegressionClassifier<CharSequence> is a generic type.
LogisticRegresstionClassifier.<CharSequence>train is a generic method.
Java Generics Tutorial

Setting Hashmap in a loop

I have the following code:
Map<String, ObjectType> objectMap = new HashMap<String, ObjectType>();
for (ObjectType obj : objects) {
obj.setSomeProperty("property value");
objectMap.put(obj.getADiffProperty(), obj);
}
It seems like during loop iteration some of the obj property changes for different keys than the one currently being set. Is there a problem with the above code? Somehow the reference to obj is being recycled by the for loop?
Also this loop is in an outer loop as well.
Update:
I am providing the full method below. The actual place where I am observing the behavior described above is in the outer map defined as Map<String, Map<String, GlossaryTerm>> loadedTerms = new HashMap<String, Map<String, GlossaryTerm>>(); defined in a Singleton class.
List<Audience> audiences = ContentAccess.getAudienceList();
List<GlossaryTerm> glossaryTerms = ContentAccess.getAllReplacementCIs();
for (Audience audience : audiences) {
Map<String, GlossaryTerm> termMap = new HashMap<String, GlossaryTerm>();
for (GlossaryTerm term : glossaryTerms) {
String definition = term.getProductGlossary().get(audience.getName());
if (definition != null)
term.setDefinition(definition);
termMap.put(term.getPhrase(), term);
}
loadedTerms.put(audience.getChannelId(), termMap);
}
I don't think what you think is happening, is happening. The object reference is what it's supposed to be, for each iteration. I think something else must be happening - that the properties are changing elsewhere, or don't have the values you think they have initially. Put in some printlns to track down what's really going on. The code you've shown can't be changing the wrong properties.
It seems like during loop iteration some of the obj property changes for different keys than the one currently being set. Is there a problem with the above code? Somehow the reference to obj is being recycled by the for loop?
The obj variable will be set to the "next" element of the iterator for objects each time around the loop. If you see the same reference value in obj more than once it can only be because:
the reference value genuinely appears more than once in collection, array or whatever given by objects, or
something in setSomeProperty or getADiffProperty or something else you are doing in the loop is updating objects as a side-effect, or
the objects object has a buggy iterator implementation.
Another possibility is that what you are seeing is different objects with the same adiff values.
To say anything more, I'd need to see more source-code than the simplified snippet you have provided.
EDIT - the extra code you provided has not revealed the problem. (I think we can dismiss any theories involving updating the lists while they are being iterated, or strange side-effects from the setters.)
My suspicion is that one of those lists that the singleton is providing contains duplicates or something else unexpected. It could be that is what is causing your problem.
Do what #Carl suggests and use traceprints and/or a debugger to figure out what is in the Collection singleton and what your code is actually doing.
EDIT 2 - The fact that the collection thingy is a singleton class is probably irrelevant. And the contents of a HashMap DO NOT change randomly or spontaneously. (And there are no little green demons in your code that conspire to make it fail. Trust me on this!)
You seem to have the mindsight of guessing what the problem is and making changes based on those guesses in the hope that they will fix the problem. STOP GUESSING! That is the wrong approach, and will probably only make things worse. What you need to do is debug the code carefully and methodically, gathering hard evidence of what your program is actually doing, and interpreting that evidence carefully ... without resorting to crazy notions that something is changing things randomly.
EDIT 3 - If I was in your situation, I would ask another experienced Java programmer in the team to sit down with me and help me debug the code. I still occasionally need to do this myself, and I've had 10 years+ Java experience and 30+ years programming experience. Sometimes you get a mental block on a problem, and a fresh mind / fresh approach is the answer.
It is not a shameful thing to admit to your team / boss that you are out of your depth and need help.
I'm starting a new answer because - well, it's a new thought here, and the discussion thread was getting rather long.
You haven't (I think) said when the changes happen. But you are (potentially) putting the same term into multiple maps, for different audiences. Nothing to do with the loop variable - just that you are repeatedly using the same list of terms, for each audience. But when you put the term into a map, you also change its definition. But the definition is (potentially) different for each audience. So, concrete example:
Term A has the definition of "x" for audience X, and "y" for audience Y. You have both audiences. Initially, we encounter audience X, so A gets definition "x". A gets added to the map for this audience. Now we iterate to the next audience, and change the definition for A to "y". This changes A everywhere you have a reference to it - including in the map for audience X. This would explain why making a copy eliminates the problem. Is this what you are experiencing?
This might be just a typo error. There is no object declared in your snippet, but your put call uses object.getADiffProperty() rather than obj.getADiffProperty(). Is that intentional?
From where the code is called? May be there are concurrent issues? Are there other threads (is it a webapp?) accessing ContentAccess? And I hope GlossaryTerm is a simple Dto, right?

Categories