Creating an 'Empty Shell' Jar - java

I'm looking on guidance on how I can essentially create an 'empty shell' jar with maven. The idea is I have a java project, and I want to export the my.project.api classes (with package) into its own jar without saving the methods / constructors actual code inside.
For example, lets say I have the following:
public class Test {
public void doSomething(String message) {
System.out.println(message);
}
}
I want to export a separate jar which would keep its package declaration, and export as:
public class Test {
public void doSomething(String message) {}
}
The reasoning for this is the project itself is exclusive, but I want to allow other developers to make their own integrations without the need of the physical product / project. This way by them hooking into say my.project.api.Test, they'd be able to see the methods and do as they wish.
Hopefully this clarifies enough, it would export as a separate jar maybe as 'MyProject-API.jar' or something.
Thanks!

This very much looks like a use case for interfaces.

Related

Gradle generate sources.jar for only public interfaces

I am working on a closed-source Android library (published as an AAR), and want to include some javadocs for consumers, which requires a sources.jar.
I know I could cherry-pick each file using an includes property or maybe even a whole package/folder.
task('androidSourcesJar', type: Jar) {
classifier = 'sources'
baseName = artifactBaseName
from android.sourceSets.main.java.srcDirs
include ('MyInterface1.kt', 'MyInterface2.kt', 'MyInterface3.kt')
}
Instead, is there a way to include only public classes, interfaces, methods, etc? This seems like a problem that would've come up before.
You could try adding something like this, instead of your include:
from 'src/main/java'
eachFile { currentFile ->
String contents = new File(currentFile.getSourcePath()).text
if(!contents.contains("public class")) {
currentFile.exclude()
}
}
I'm not entirely sure if that works, but it should set you on the right path to where you want to go.
Since Gradle does not actually do any code analysis, you can't just simply say "only include files that have classes that are public". Instead, you have to either write a custom plugin that will only include public classes, or do something like what I provided. It includes everything from the source directory, but runs a little bit of code on each file. First, it gets the contents of the file, then it checks if that file contains public class. If not, the file does't have a public class, and should be excluded.
Hope this helps! Feel free to ask any more questions if you have any.

How do I use IKVM from IronPython?

Let's say I'm writing an app in IronPython and I'd like to use some classes stored in a Java jar (which I don't control and I'd rather not wrap in a DLL).
I downloaded IKVM and tested that command line tools work fine.
Let's say the class I'd like to access is like this:
package some.thing;
class Hello {
public static void myMethod(String arg){
System.out.println("you got me!");
}
}
Which DLLs should I import from IronPython in order to be able to then call Hello.myMethod('a')?
Is this possible at all with IKVM? If not, is there any other way you can see to make this work?

How to use java methods defined in another class/file

I've been working on some problems from Project Euler, and, in the process, have written a lot of useful methods (in Java) that I might like to use in other Java projects. I want to be able to call them in the way that you call a function from java.lang.math, so if I had a method primeFactor() I could call it using MyMathMethods.primeFactor(number). How would I go about this? Would I make some kind of package that I could import? Would I make a superclass that includes all my useful math-y functions and have whatever class I'm working with in a new project extend that? There are probably multiple ways to do this, but I don't know what is best. Thanks in advance.
Mark your utility methods as public static. Package your classes containing those utility methods in a jar. Add/Refer that jar in your project, where you want to use the. Then in your code you can call them in a static way lke : MyUtilityClass.myUtilityMethod();
The best thing for this situation is to work in meaningful packages and make their jar
You can create a package like
/* File name : Animal.java */
package animals;
interface Animal {
public void eat();
public void travel();
}
Also on classes
package animals;
/* File name : MammalInt.java */
public class MammalInt implements Animal{
public void eat(){
System.out.println("Mammal eats");
}
public void travel(){
System.out.println("Mammal travels");
}
public int noOfLegs(){
return 0;
}
public static void main(String args[]){
MammalInt m = new MammalInt();
m.eat();
m.travel();
}
}
You can import them like
import animals.*; OR be more specific import animals.MammalInt;Now you can make the jar file , import it in your project and use its methodYou can eaisly do it by this commandjar cmf MyJar.jar Manifest.txt MyPackage/*.class
For more details about jar creation please see thisAs a side note: Be carefull about visibility of members and functions while packaging itBecause there usage and accessibility matters a lot while we are using them
You could create separate java project with your util classes only and then create jar file and import into any another project.
Simply instantiate the class. Like your example, if you had a class MyMathMethods with the function primeFactor(number) then at other classes, simply instantiate it with something like private MyMathMethods myMathMethods;. Now, to call the function simply do myMathMethods.primeFactor(number); You may need to import its package as well.
False understanding of packages is any class defined within a package is visible to all other classes. Not true from my experience. If you have classes containing utility style methods you want to make available in another class? Simply declare a new instance of the class in the class you need the method in. Like... private MathUtilsClass mathUtilsClass = new MathUtilsClass(): Then any method you want to call from this class uses the new identifier, e.g. mathUtilsClass.greatFunction(); This is stupidly easy and should solve your problem.

GWT: How to share a java Object (ie: EventBus) between two modules

I’m building a large application and I would like to split it in several modules like Core Module for initialization, users management, etc…, Customer Module, Production Module, etc…
I want to split it in multiples GWT modules (not using GWT splitting technique) and share an EventBus for broadcast some events like LoginEvent, LogoutEvent. I don’t want uses the code splitting technique because I want reduce the compile time and re-compile only the module that I modified.
This allow also to enable or disable a module by commenting the script tag in the HTML host page.
I’ve write the following code with using JSNI:
CoreModule’s EntryPoint:
private static SimpleEventBus eventBus = null;
public void onModuleLoad() {
export();
getEventBus().addHandler(MyEvent.TYPE, new MyEventHandler() {
#Override
public void onEvent(MyEvent myEvent) {
Window.alert(myEvent.getMessage());
}
});
}
public static SimpleEventBus getEventBus() {
if (eventBus == null)
eventBus = new SimpleEventBus();
return eventBus;
}
public static native void export() /*-{
$wnd.getEventBus = $entry(#testExporter.client.TestExporter::getEventBus());
}-*/;
CustomerModule’s EntryPoint:
public void onModuleLoad() {
Button button = new Button("Click me");
button.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
getEventBus().fireEvent(new MyEvent("Button clicked !"));
}
});
RootPanel.get().add(button);
}
public static native SimpleEventBus getEventBus() /*-{
// Create a useless eventBus because the GWT compiler make a call to a null instance
var eventBus = #com.google.gwt.event.shared.SimpleEventBus::new()();
eventBus = $wnd.getEventBus();
return eventBus;
}-*/;
But I’ve the following exception in Firebug when executing in the browser:
uncaugth exception [object Object]
I copied also the MyEvent and MyEventHandler classes that implements/interfaces a customer event.
P.S.: I know also the technique that consist to comment the other modules references to avoid to compile it.
A simpler answer is to not use multiple entry points.
==========================================
If what you are trying to achieve is breaking you code into manageable units but want to use all of them in the same page, you can:
create an "Application.gwt.xml" module with an entry point (equivalent to your initialization module, if I understand correctly)
create "UserManagement.gwt.xml" module without an entry point class
create other XXX modules without entry points
To create a module without entry point just remove the
<entry-point class='xxx'/>
from your gwt.xml files except for the "Application" one
You then need to include these modules into the "Application" module using
<inherits name="com.yourpackage.Module1Name" />
<inherits name="com.yourpackage.Module2Name" />
You then need to compile all of them together in one GWT build for module "com.yourpackage.Application".
When you do that make sure that both the compiled *.class and the source .java files for all your modules are available on the classpath.
Your "Application" entry point just needs to initialize and use the objects from the other modules
You cannot share code between different GWT compiled modules, unless you make some parts of your code available via jsni and call these exported methods via jsni, like you are trying in your query.
But be aware that: first, shared classes would be incompatible because each compilation would rename the classes/methods in a different way, and second, each compilation would remove different dead code pieces.
So in your case the SimpleEventBus returned in your window.getEventBus exported method is not known in other modules, although the other modules are using SimpleEventBus as well
The easiest way to do what you want, is to use GWT-exporter. First select correctly the js-api you want to export in each module, how you want to name it, and implement Exportable and annotate methods conveniently. Second take in account which objects would you use for the communication, because some of then could be incompatible. I would use primitive types, javascript object, and functions which are supported in GWT-exporter
I think that with GWT-exporter, for shared classes, if you annotate them in the same namespace and you export the same methods, hopefully you could use then in all modules but I'm not sure.
So export a js API via jsni or gwt-exporter and transfer pure primitive or js objects between them.
You can use the Frames and setup communication between the modules via WebMessage protocol. It will help only if the modules in one page and modules in separated war.

Modifying JAR files without rebuilding the JAR

I have a JAR file that I'm using and I want to modify one of the files inside it. In a nutshell I have
public class ClassB {
public void printMethod(){
ClassA A = new ClassA();
A.printout();
}
}
public class ClassA {
public void printout(){
System.out.println("1234");
}
}
and I want to change ClassA's printout method to
public class ClassA {
public void printout(){
System.out.println("abcd");
}
}
I know you cannot modify a JAR without unpacking/rebuilding it and for this, let's say I can't do that. Is there a way to make modifications to ClassA without actually touching the current ClassA? My approach is to have a new class inherit from ClassA with an overridden method and then have a new class inherit from ClassB that calls the Inherited ClassA
public class InheritedClassA extends ClassA{
#Override
public void printout(){
System.out.println("abcd");
}
}
public class InheritedClassB extends ClassB{
#Override
public void printMethod(){
InheritedClassA A = new InheritedClassA();
A.printout();
}
}
I don't like this approach though because in my actual JAR, so many classes are using ClassA that its a nightmare trying to correctly do this with all of them, which then all require the same process on them. I know you cannot overload/overwrite a whole class which is basically what I want to do. Is there another way to do this?
EDIT
To make it even harder, I cannot download any new frameworks or software or anything.
I can only provide pointers as I never felt the need for it.
What you are referring to is called "Bytecode enhancement", and yes there are several frameworks to achieve it.
BCEL - http://commons.apache.org/bcel/
ASM - http://asm.ow2.org/
Usually, java developers prefer to use the inversion of control pattern. This allows the code to configure itself at runtime via a configuration file - See Spring IoC for more details.
One option which may not be feasible would be to create a new version of ClassA, package it up in its own jar file, and put that ahead of the original version in your classpath.
However, this is a pretty odd scenario - why can you not update the existing jar file? Even if that means a bit of extra work, it's likely to be much cleaner in the long run than any other approach.

Categories