I program a class in which I have a method which takes an callback object from an external software. At the moment Eclipse says that it does not know the type of the object I gave as argument (it is expectable since I do not specify this type, it's done by the external software).
So, I think I need to write an interface for the object which I give as an argument to my method. In this respect I have two questions.
Is it really so? Can I solve the mentioned problem in the mentioned way.
If it is the case, where should I put this interface? In the same file where my class is? In the class? Outside of the class?
If the object is from "external software", then they should be providing you with some kind of API so that you can manipulate/inspect the callback object. So what you likely need to do is get the other software's API library and add it to the path for your eclipse project. Then eclipse should know eveyrthing it needs to about the object.
Related
I am making a command framework API. People will use my API in their own project.
I have detected all #Command annotations, and when I trigger the command I invoke their attached method.
The issue is I need to be able to either load these classes, or get the live instance. This is because they may have chosen to load the command class themself if they, for example, use a constructor to pass data. Or not.
I've got the former worked out (which works fine):
mapping.getMethod().invoke(mapping.getMethod().getDeclaringClass().newInstance(), paramValues);
But this errors if a live instance exists. How can I get the the live instance?
This is a tricky situation as I am trying to do this for THEIR classes not mine, so I have a lot less available to me. I'm happy to use reflection or whatever hacky methods you come up with.
For example i want customize BluetoothGatt class. Is it possible to create android.bluetooth package and put own version of this class?
BluetoothGatt uses android interface files shown in here. Can i access these files and use it in own version of BluetoothGatt?
Yes as long as you match the package and class name, when you reference it in your code, you will be able invoke your custom behaviour / modified contract
Android classes are simply Java. You can modify the support SDK, as it is simply a Java file. However, this is only applying to your app, or it would be possible for apps to change the entire SDK, which is defeating the point of sandboxing. If you want to extend the class, that is done just the same as in Java, as the class is just Java. However, this specific class is final, so you can't, at least not without hacks. However, the support library is usually a wrapper, so you may as well write your own. If the reason you want to do this is to access a private method, use reflection!
EDIT: To pedantically answer your question, you have already accessed said files, and copy-and-paste is always your friend!
Hope I helped!
I have a library class that is a singleton and does NOT implement any interface (So I'm assuming I cannot use dynamic proxies). But, I need the same functionality as the dynamic proxy. I need to hijack the call, log some data and pass on the call to the library as is.
Is it possible to do this without having to use AspectJ or Spring AOP? (I'm not sure how to use these frameworks, but I will have to look into it if there is no other way).
You can provide your own implementation of the same class, with the same name and package, and try to put it into classpath first. The calling code with such classpath will pick the intercepting class first, and the intercepting class can call others classes of the actual package to provide its actual functionality.
Best would be to remove the overridden class from the library .jar with archive tool.
You could change the import statements in the classes that call f() so that they see a different class that implements f(). The implementation of that class would do the logging and call the real f().
Still requires some editing, but less than changing every call.
BTW: Depending on the size of the project, you may want to consider making wrappers to that "black box" anyway, if this type of requirement will be ongoing.
Like I started in my comment wrapper all the classes you implement from the external library. Then call the external library from your own classes this way you can log in the function(s) you want. If you use the same function name then you don't have to change what you call you only have to change your import(s). Most IDEs provide mass name replace so it shouldn't be too big of a burden it will be tedious however.
I'm looking for some ideas on how to compile Java code with some other pieces of code missing (method calls). I am fully aware that javac will not allow you to compile Java files if cannot find all dependencies. But maybe there is some way how to bypass it, something like force compile.
My bytecode knowledge is not so good but I think some method invoke is just full package definition of class and method name with parameters. So if compiler just puts this data to class file and assume in running process dependency will be available (if not simple NoSuchMethodExp).
Only workaround so far I found is to create empty missing class files with empty methods to "cheat" compiler. Works perfectly but there should be easier way :)
Any ideas?
Use Interfaces.
Create the interfaces that have the methods you need. At runtime, inject (Spring, Guice, etc.) or generate (cglib ...) classes that implement the interface.
If you're modifying a jar, you can extract the class files you are not modifying to another directory and include that in the classpath. That way they will be available to the compiler.
Bad luck! Probably all you can do is to create mock objects for missing parts of code just to compile your code (empty methods, so the compiler can find it).
Another question - if you miss some classes, how will you execute that code?
UPDATED according to information provided:
Well, there is another option to modify classes in jar, you can use AOP, and to make it done read about AspectJ - actually for me this is the easiest option (typically you need to spend time mocking objects, writing empty methods, so I would contribute that time to study new technology, which will help you many times ;)
And btw the easiest way to implement it, if you use Eclipse, is:
install AJDT
create aspect project
create aspect which modifies code (depending on what you need to change)
add jar file you want to modify
immediately get modified code in
another already packed jar file
Sounds magically :)
In this case you don't need any dependencies in classpath, except for libraries which are needed for new code you add!
Methods aren't dependencies. They are part of the class definition. The only places the java runtime looks for method definitions is in the class def that was compiled at compile time and in its parent classes. If you're problem is that a super class is incomplete, I don't think I can help you.
If not, you could define some of these methods as abstract and than have a child class implement them.
What kind of code is missing? Normally this happens if you refer to libraries your compiler can't find. Maybe you simply need to extend the classpath the compiler is searching for classes.
If you really refer to code that is not available yet you need to implement at least those methods you refer to. But that sounds strange... maybe you can clear things up.
I have a functionality that I wish to provide to a customer for a software mockup that we are preparing - and I want to know if it's
possible
intelligent (a.k.a. not stupid)
the best thing
I want the customer to be able to write a java class that implements my Computable interface and stick it in some predetermined folder. This folder will contain the .java files rather than .class files. Then, at runtime, I want my program to search that folder and extract all of the Computables from that folder and store them in a map from the name of the Computable to the Computable object. The Computable should only have a default constructor and the it interface will only have one method called compute which maps an array of Object to an Object.
The Java Compiler API introduced in Java SE 6 should give you what you need.
You may find Google Reflections useful to find classes implementing/extending a certain interface/superclass in the classpath. It's then as straightforward as
Reflections reflections = new Reflections("my.project.prefix");
Set<Class<? extends SomeClassOrInterface>> subTypes = reflections.getSubTypesOf(SomeClassOrInterface.class);
Then, to test if it indeed has a no-arg default constructor, just check for each if Class#newInstance() doesn't throw any exception.
There are several suggestions provided as answers to this question.
Here too On-the-fly, in-memory java code compilation for Java 5 and Java 6
If it's easy enough to compile at runtime that would be fine.
You can use javax.tools to do the compilation as needed. Create dynamic applications with javax.tools may help, too. It's also possible to do it in memory.
One caveat: using the compiler creates a dependency on the JDK; the JRE alone is insufficient.
take a look: Find Java classes implementing an interface
I think this would be simpler if you allowed your customer to type in a code declaration using something like Groovy, which is Java-ish enough, and easy to execute at runtime from a String value.
It's easy enough to iterate through the list of files in a folder. Someone mentioned that it's possible to call the Java compiler from Java (if you re-distribute the JDK, which I think is a point whose legality needs checking!!) That's much of the battle.
You seem to have a fixed model in your mind where only files fulfilling a certain interface are extracted from the folder. I think this is where your method needs to give a little. The sensible way (IMO) to do this would be to compile all files in that folder, and then with their classes stashed away somewhere, you can load and reflect them and then determine which of them "do" the interface and which don't. Those that don't will have been needlessly loaded into your JVM, but unless it's intentionally very space-wasteful, code you don't execute can't harm your program.
Having determined which ones do the computable thing, you can then store those classes (or instances thereof) in a Collection and do whatever you like with them. You simply ignore the other ones.
You could use BeanShell. This library is small and doesn't require the JDK. It is used in a number of IDE and web servers. The latest version appears to have the support you need loading .java files from the class path. (Still in beta)