Replace Eclipse library class with my own - java

I'm developing an Eclipse plugin in which I want to overwrite the functionality of a method contained in a class that is in the Eclipse library.
What I've tried so far is creating an identical (same package and file names) file in my plugin source, and making the changes I want there. Then, I set the build path order such that my source is above the Plug-in Dependencies. Based on my limited understanding, this should mean that when Java looks for that class, it should use mine over the one in the library.
However, this is not working. The behavior that I want to override is not changing, and I don't see the print statements I put in my code either.
How can I "replace" a class in the Eclipse library with one of my own?

I did it once (not proud of it :-)) in the following way:
Import the plugin you wish to hack by Import->Plugin Development->Plug-ins and Fragments (Import as Projects with source folders).
Set the project to build automatically, edit the file and find its resulting class file.
Open the jar of the plugin (the one containing its class files), inject your class file instead of the original one.
If jar file is signed remove all signature information from MANIFEST.MF (and maybe other files).
I admit it's ugly but it's the best way I've found.

I ended up using the JVM JavaAgent to achieve this, by overriding the class loader and loading in my own class to replace the one in the library.
This was a useful tutorial for me: https://stackoverflow.com/a/11898653/634324

Related

IntelliJ doesn't pick up generated .class files

I have implemented an AnnotationProcessor that picks up class annotations that take a string argument. The string argument is an expression in a domain-specific language, which the annotation processor will use to compile a class file.
I create a small test project to try this out. The behaviour I see is this:
I can successfully build the project using maven
I can successfully run the project from within intellij
Despite the project RUNNING in intellij, the generated class is not recognised in the editor ("Cannot resolve class '...'"), and intelli-sense does not work, either.
I've tried to find the issue and found:
the class file that is being generated is being created in target/classes/package/name/KlassName.class (this is the location that the Filer::createClassFile method picks, I'd have expected this to go to some separate directory though).
if I'd create a java source file during annotation processing (using Filer::createSourceFile), intellij would have no problem. However, I can't do that, since the compiler is a library that really must create classes directly.
I have two guesses about what a solution might look like:
This problem might stem from intellij not looking inside target/classes when type checking in the editor window.
The class files should be generated in a separate directory instead. If so, what is the setting to fix that?
I have reproduced this issue using intellij IDEA 2016.2.1 and intellij IDEA 2017.2 EAP.

AEM 6.1 Sightly Java class does not update on build

I have recently started using Sightly in AEM 6.1, which allows the Java files to be located in the same folder as the component and use the WCMUse class. However, I am noticing that whenever I do a Maven build that involves a change to one of those Java files that the page functionality operates as if the Java class had not been changed, though the Java file in the crx does include the changes. As a workaround I have been been able to modify the Java file in the crx, save it, then modify it back and save again in order to update the functionality, but I do not have that capability on all of my instances.
Anybody have an idea how to force the recompile of the Sightly Java within the components either during or following the build?
A few things to validate:
1- Do you change the version of the software when doing a maven build/deploy? Sometime if your zip or jar does not have -SNAPSHOT in it AEM won't update the code when maven deploys.
2- there a /var/classes/sightly in CRX/DE that you can delete compiled classes, I think even in the system console there is an entry
Hope this help.
Bambara actually helped me get to the answer that I needed. It turns out the /var/classes folder holds the compiled sightly files, but it doesn't naturally recompile on build. Deleting that folder on build, then running a page that uses the sightly code forces a recompile and shows the new functionality.
Hopefully others can answer why this happens and how to avoid it. Having faced this a number of times, I'm beginning to think placing Java code into the component folders is not a very good idea. Using a maven multi-module project with a Services/Core bundle, then all Java code could go there. Calling it from the view just requires using the fully qualified classname (including the package). Placing the Java into the services bundle has the following benefits
Allows the classes to be extended. For some reason compilation was unpredictable when extending classes from component folders.
Easier IDE setup. Java classes in component folders in the view module have a Sling specific folder structure, so getting IDE's to provide code assist requires extra effort.
Sling folder conventions follow URI practices and might have dashes, Java packages cannot have dashes... import apps.my-cool-project.components.pages.base.Header; // won't compile

IntelliJ Idea keeps linking to library files even after creating the file again locally

I have a class BaseLoginDialog under a dependency which needs to be modified as it is not extendable out of the box. For this reason, I have created another file BaseLoginDialog under my project's module with the same package path as the original BaseLoginDialog. After adding some new methods in my own local BaseLoginDialog, I cannot use them anywhere in my project without IDEA complaining about the method not being declared. However, the project still compiles and the methods work fine on runtime. If I click the import to browse to the file, IntelliJ still links to the old file but it seems to correctly compile with the new one.
How can I go about fixing this issue? Always having error lines and red markers everywhere makes it confusing when coding.
Some background:
The project uses Gradle for the dependencies and compilation. Compiling and running works both with Gradle and with the IntelliJ run operation, it is only the errors being incorrectly displayed that is an issue.
The Grade file adds the required libraries as dependencies. Even though Gradle has both the source and class files, opening a file imported through Gradle still links to the class files. To get around this I also added the required files as sources under Libraries.
Any help would be appreciated, thanks!
EDIT:
Switched to use a Maven repo on the project, now I don't need to additionally add libraries anymore but this problem still persists.
If two classes of the same name and package exists in the classpath of an application, it's the one that is contained in the first dependency on the command line that gets used.
In IntelliJ, you can reorder dependencies, so you can put your local dependency before the other library. I'm not sure if that works with gradle projects, however.
But I don't think that's a good practice? Why can't you put the extra methods in a subclass, e.g. EnhancedLoginDialog, and use that one?
Or, if the original library is open source, fork it, make the changes and install it as a custom version, e.g. dialogs-1.0-CUSTOM-1.jar, and use this version in your project. And while you're at it, create a pull request for the library's maintainer to include your fixes in the next version :-)
I have resolved the issue.
The file I was copying into my local files was BaseLoginDialog. The file showing errors was my NewLoginDialog which extends LoginDialog which extends BaseLoginDialog. It seems that when IntelliJ goes to my NewLoginDialog, it sees that I have extended LoginDialog. Therefore it jumps into the library files and finds that LoginDialog extends BaseLoginDialog, now when it goes to find BaseLoginDialog, it uses the library files and ignores my local copy of BaseLoginDialog.
Essentially, once IntelliJ branches into a library, it does not move back out when looking for additional files if it can already find it inside the library.
To solve this issue, I simply also copied LoginDialog locally, even though it is identical (simply branched it and did not change anything). Now IntelliJ finds LoginDialog in my local files and as a result also finds BaseLoginDialog locally.
Hope this helps anyone having the same problem in the future.

How to create .jar library from class in Intellij IDEA

I am trying to learn java and have implemented a single, and simple, class in Intellij IDEA 14.1.3. I want to be able to use this class in other projects without copy and pasting the class source into each project src directory. Essentially, I want to create a package, or module (I'm not sure which, which is part of the problem) that I can simply import into any projects's src that I am working on--kind of like my own, one-class, library. While trying to figure out how to do this, I came across the two following blog posts--
http://blog.jetbrains.com/idea/2011/10/new-in-11-create-library-from-project-view/
http://blog.jetbrains.com/idea/2010/08/quickly-create-jar-artifact/
--but when I tried to do what they instructed (creating artifacts in Project structure, etc.) I wasn't able to because my class doesn't have a main() method, as its not meant to. So I was wondering if I was going about this right--is there a way to do this, or am I stuck with copying and pasting?
I managed to get it--I had to go into Project Structure and set it to create a jar file containing my compiled .class file upon build. Then I could add the jar file as an external library in my other projects. Thanks guys for the replies.
You only need a main method if you want the package to be able to run as a standalone application.
So, to answer your question: no.
You don't need a main method to create a package, nor to import or use the package/library in a separate application.

Using apache.commons.lang in more eclipse plugins

I am facing to the following problem:
I would like to use SerializationUtils from apache.commons.lang. Since it is part of the eclipse platform, it seems easy. However, when deserializing, it does not find the classes in my plugin.
And I don't want to hack the manifest.mf of apache.commons.lang (adding Eclipse-BuddyPolicy: dependent), because I have to create a jar for a third-party component, which runs under tomcat6, and tomcat6 complains about wrong manifest.mf, if I hack the manifest.mf.
So basically I would like to use apache's SerializationUtils in 2-3 independent plugins without hacking apache's jar. Is it possible?
Its most likely you need to supply an appropriate ClassLoader to find the class for a given app. A class can be loaded many times in different applications and the ClassLoader determines which is the right copy to use.
I don't see how changing the manifest would help.

Categories

Resources