Casting issue with maven but not eclipse - java

I am facing a type casting issue I can't figure out a workaround for.
The context is a legacy project developed in java 6 which has project B depending on project A.
Currently the build process involves generating .class for project A and copy them manually into project B before building it. It is very awkward but it works.
The issue arise when I tried to define the dependencies into the pom so that we can get rid of the manual process and let maven deal with the dependencies.
Here is the code that cause the error:
List<RowFilter<MyTableModel, Integer>> filters = new ArrayList<RowFilter<MyTableModel, Integer>>();
myTable.setFilter(RowFilter.andFilter(filters);
with setFilter defined as:
public void setFilter(RowFilter<MyTableModel, Integer> filter)
The error I get is:
setFilter(javax.swing.RowFilter<javax.swing.table.TableModel,java.lang.Integer>)
cannot be applied to
(javax.swing.RowFilter<java.lang.Object,java.lang.Object>)
I need to understand why is it working in the current build process but not when using maven dependencies? And how to fix it.
Thanks

After playing a little bit with casts I found the following to work:
Do it in each call to setFilter (more than a dozen)
myTable.setFilter((RowFilter<TableModel, Integer>) (Object) RowFilter.andFilter(filters));
Or redefine the setFilter signature like this
public void setFilter(RowFilter<?, ?> filter)
Or like this
public void setFilter(RowFilter filter)
Can anyone explain why it was not working in the first place and why this is working? Or if there is a better workaround?
In the meantime, i opted for the second option.

Related

Using external classes with dataflow

I am trying to make a custom transform class that takes in a side input and I am using PipelineTester and PAssert to try and test it, but I keep getting a no such method exception on methods I am trying to bring into the transform from other classes.
Caused by: java.lang.NoSuchMethodError:
com.org.utils.MyUtils.createMap(Ljava/lang/Iterable;)Ljava/util/Map;
at com.org.beam.MyTransform.ProcessElement(MyTransform.java:51)
I have tried using the #Autowired annotation to bring in the class like
#Autowired
private MyUtils myutils;
as well as just creating a static instance in the code like
private static MyUtils myUtils = new MyUtils();
and then calling
this.myUtils.createMap(mapThisToThat(inputCollection, this.myMap));
I have also tried making the methods static and calling them like
MyUtils.createMap(mapThisToThat(inputCollection, this.myMap));
the signature to mapThisToThat is
private Iterable<MyObject> mapThisToThat(Iterable<MyObject> objectIterator, Map<String, Integer> myMap) {
which is being passed into the createMap method which has this signature -
public Map<String, MyObject> createMap(Iterable<MyObject> inputCollection){
so it is passing in an Iterable of MyObjects correctly, but it says the method doesn't exist for some reason. does this mean beam transforms can't have external methods or am I doing something wrong?
For me in python, there are a variety of things I need to do for that to work:
https://cloud.google.com/dataflow/faq#how-do-i-handle-nameerrors
https://beam.apache.org/documentation/sdks/python-pipeline-dependencies/
For you in java, they don't have reciprocal documentation for some reason, but over here https://beam.apache.org/documentation/runners/dataflow/ they say things like this:
In some cases, such as starting a pipeline using a scheduler such as Apache AirFlow, you must have a self-contained application. You can pack a self-executing JAR by explicitly adding the following dependency on the Project section of your pom.xml, in addition to the adding existing dependency shown in the previous section.
In their examples readme https://github.com/mbrukman/apache-beam/tree/master/examples/java they say this
Alternatively, you may choose to bundle all dependencies into a single JAR and execute it outside of the Maven environment. For example, you can execute the following commands to create the bundled JAR of the examples and execute it both locally and in Cloud Platform
If you continue to browse that examples repo, there is a common folder with utils. Hopefully you can copy how they did it.

java.lang.NoSuchMethodError related with a class constructor

I have the following class signature:
public BlockstemRequester(RateLimiter throttler,
String url, List<String> payloadsToBeRequested, List<String> objRef) {
.
.
.
}
And I'm using that constructor at this following code:
threads.add(new BlockstemRequester(RateLimiter.create(1.0),
String.format("url...", apiKey),
chunks.get(index),
chunksObjRef.get(index)))
where:
RateLimiter is from import com.google.common.util.concurrent.RateLimiter
chunks is defined as val chunks:util.List[util.List[String]] = new util.Vector[util.List[String]]
chunksObjRef is defined as val chunksObjRef:util.List[util.List[String]] = new util.Vector[util.List[String]]
But, unfortunately I'm getting an error telling me that class constructor was not found or defined:
java.lang.NoSuchMethodError: BlockstemRequester.<init>(Lcom/google/common/util/concurrent/RateLimiter;Ljava/lang/String;Ljava/util/List;Ljava/util/List;)
Basically, I'm using this class defined in Scala at my java code project, and I did defined the scala class to use List from java to avoid any problem of incompatible types between the languages.
At runtime I'm getting this following types according to my debug process:
chunks is a Vector[Collections$SynchronizedRandomAccessList]
chunksObjRef is a Vector[Collections$SynchronizedRandomAccessList]
I appreciate any kind of help towards this problem. Thank you!
As per Java docs:
Thrown if an application tries to call a specified method of a class
(either static or instance), and that class no longer has a definition
of that method. Normally, this error is caught by the compiler; this
error can only occur at run time if the definition of a class has
incompatibly changed.
From you question it is not clear if you are getting this at compile time or run time but looks like you are having issue at run time. So, use a Java decompiler and check the .class of this class whether this method is present or not.
Most probable root cause of this issue is that library used at compile time have such a method but library used at runtime doesn't have it, and hence NoSuchMethodError.
Use decompiler and check .class file of the class.
Just solved the problem. So this was the scenario: I have a project X and using a library Y. So both X and Y have different definition of the class BlockstemRequester, both with different constructor signatures. I had to change that class name of my project and refactor my code. So, at runtime the constructor pointed out it was that one from my project X and not from that one defined in the library Y
I appreciate any advise if there is any way to approach this problem better than just renaming/refactoring my local classes
I think that the problem is with your 'typed' list.
If you change the signature to
public BlockstemRequester(RateLimiter throttler,
String url, List payloadsToBeRequested, List objRef)
Or
public BlockstemRequester(RateLimiter throttler,
String url, List<?> payloadsToBeRequested, List<?> objRef)
This will work.

Eclipse gives error for 'undefined' Java function it can easily find

I've been having trouble with Eclipse. I'm working on a java project that's configured with git. After submitting my code through git, Eclipse suddenly generates all these errors, saying many functions are undefined. However all the functions are still there, Eclipse will even take me to them when Ctrl+click the function.
For instance say I have this class:
public class myClass {
public myClass () {}
public void myFunction () {
//do some stuff
}
}
And now I have another class that uses it:
public class secondClass {
public void callFunction () {
myClass a = new myClass();
a.myFunction();
}
}
The myFunction call in secondClass causes an 'undefined' error in Eclipse. I've tried refreshing the project but it doesn't make a difference. The only way I've found to get Eclipse to behave correctly is to comment out the function it can't find, uncomment it, and then save the file. Is there a better way to do this? Or prevent Eclipse from having this problem?
Sounds like something is going wrong with your eclipse.
When this happens I typically do the following. (Continue to the next bullet if previous did not help):
refresh the project. First try F5. If it does not help do it using right click on project and choosing the appropriate option in context menu. It is strange, but sometimes F5 does not work, but menu does.
rebuild the project.
Try to close project and open it again
try to delete project (without removing content) through Eclipse.
try to create project again and copy *.java files there.
try to create new workspace.
I hope that #1 (or probably #2) will help.
Check if you have properly imported myClass in secondClass.
Secondly, your class naming is wrong. Class names generally starts with a capital letter.
From your 'solution' it seems to me the imports have gone missing. Commenting and then uncommenting the method and saving the file caused eclipse to fix your imports.
You have to take a look at the way you commit/push your code through git (and who did the last change), there is probably something wrong in the workflow that causes them to commit a file with missing import statements.

Testing ServiceLoader in Eclipse Plugins

I have four Eclipse plugin projects (create a new Java Project, right-click, configure, Convert to Plugin Project) in my workspace. The first (my.runtime) contains an interface (MyFactoryInterface) and a class (MyClient) that defines a method (List<String> getAllFactoryNames()) that loads all implementations of that interface via java.util.ServiceLoader and calls a method (String getName()) on them, collecting the results and returning them in a list.
To test that class, I have a JUnit test in the second project (my.runtime.test, set up with my.runtime as Fragment-Host), checking if the name returned by a dummy implementation(MyDummy, returning "Dummy") I have in the my.runtime.test project is in the list returned by MyClient.getAllFactoryNames(). So far, it works fine.
In the third project (my.extension, with my.runtime as dependency) I have a class (MyHello) that uses the names returned by MyClient.getAllFactoryNames() to return a list of greetings ("Hello "+name).
Again, to test this, I have a project (my.extension.test, with my.extension as Fragment-Host) containing another Implementation (MyWorld, returning "World" as name) and a JUnit test case checking if "Hello World" is in the greetings returned by MyHello.getGreetings(). This test fails, as MyClient still only finds the MyDummy implementation, and not the MyWorld implementation. Both implementations are accompanied by matching entries in META-INF/services/my.runtime.MyFactoryInterface files.
I currently use the following code to load the implementations:
ServiceLoader<MyFactoryInterface> myFactoryLoader = ServiceLoader.load(MyFactoryInterface.class);
for (MyFactoryInterface myFactory : myFactoryLoader) {
I know that I can supply a ClassLoader as a second argument to ServiceLoader.load, but I have no idea how to get one that knows all plugin projects... any suggestions? Or is ServiceLoader not the right tool for this problem?
If anyone stumbles over the same problem: the combination of ServiceLoader.load(MyFactoryInterface.class, Thread.currentThread().getContextClassLoader()) in MyClient and Thread.currentThread().setContextClassLoader(MyWorld.class.getClassLoader()); in the second test did the job.

Same source code, Eclipse build success but Maven (javac) fails

Keep getting this error when compiling using Maven:
type parameters of <X>X cannot be determined; no unique maximal instance exists for type variable X with upper bounds int,java.lang.Object
Generics type interference cannot be applied to primitive types. But I thought since Java5, boxing/unboxing mechanism works seamlessly between primitive types and wrapper classes.
In any case, the strange thing is Eclipse doesn't report any errors and happily compiles. I'm using JDK1.6.0_12. What could possibly be the problem here?
This issue can occur when your code is generic and it calls another method that has a generic return type. Sometimes the compiler gets confused trying to figure out how to resolve the method call / return type.
It can be resolved by adding an explicit cast to your code.
// Old code:
public T getValue() {
return otherMethod(); // otherMethod has the signature: <RT> RT otherMethod() { ... }
}
// New code:
#SuppressWarnings("unchecked")
public T getValue() {
return (T) otherMethod(); // the cast tells the compiler what to do.
}
A few things to look at:
Both Eclipse and Maven are using the same java/bin installation
Eclipse and Maven are using the same libraries, one might have something the other does not.
I met the same error,use ant.
Because when compile by ant or maven,javac use JDK to compile.But in eclipse,it has JDT,that can compile success.
I add below script in my build.xml file:
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter" />
Then,ant can build success.
I am not familiar with Maven. Maybe,it can set the compiler?
In my source code,there are many code like this:
public <X> X find(String hql, Object... values)
{
return (X) HibernateUtils.createQuery(getSession(), hql, values).uniqueResult();
}
Maybe your code too.
But,use JDT,the success is't the final success,in ant.
build.xml can build success only in eclipse.
when I run ant from windows command,fail. Throw another error:
Class not found: org.eclipse.jdt.core.JDTCompilerAdapter
PS, I have copy jar files about JDT in eclipse plugin to ant_home/lib directory.
Wish a little help to you.And our problem can solve.
It definitely has to do something with the JDK versions maven and eclipse are using. Also make sure your Compiler compliance level in eclipse points to the right JDK version.

Categories

Resources