How to build automatically different JARs from same code using Eclipse? - java

I have many more classes in the project but for now please consider only A, B and C classes.
abstract public class A {...}
public class B extends A {...}
public class C extends A {...}
Then later I have a code, say in class D, like this
A a = new B();
//A a = new C();
//use a's methods
So my question now is how to easily configure in Eclipse building of two separate JARs. First one should have B.class included and C.class excluded and code as A a = new B(); The second one should have C.class included and B.class excluded and code as A a = new C();
I do not know many things about Ant and Maven. Do I need to use them in this case?
Maybe, something wrong with my design, if so, please let me know.

What you want to is mainly a code loading problem, not an Ant problem.
Just the two statements you presented for creating a new class instance:
A a = new B();
A a = new C();
The constructors are called using static code. Ant can not change the code, therefore the only way with Ant I see is generating a Factory class with Ant as part of the build process, depending if A or C is included into the JAR
But that would result in a project that can no longer be used directly in Eclipse as the original source code in the Eclipse project misses the factor class.
A IMHO better approach is dynamic class loading (may be combined with reflection). You can automatically search for classes that extend A or you add a configuration file/info to the JAR specifying which class to create (e.g. properties file).
Place the properties file in the src folder with the Java file and load it via this.getClass().getResource("myclass.config");
The config file can contain the class name that should used for creating a new instance.
The following code snipped assumes that B and C both have a public constructor that does not take any argument:
String classNameToLoad = ... // loaded from config file example "mypackage.B"
final Class<?> c = Class.forName(classNameToLoad);
final Class<? extends A> ac = c.asSubclass(A.class);
final Constructor<? extends A> a_ctor = ac.getConstructor();
final A a = a_ctor.newInstance();

In your eclipse you if you right click your project, you will have an option Export
Click on that, and select jar, then name the jar, select the classes you want in it.
Repeat this for the other jar.
check this http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftasks-33.htm

The easiest way to do this would be to have 3 separate Java projects in Eclipse. Based on your example, that would be
B code project
C code project
A common code
Eclipse allows you to reference the bin directory of another project from your project in the build path.
Then you can export (or use Ant) the B and C projects as separate projects.

Related

Import .jar libraries in VS Code

I need to use a .jar library, given by my teacher, to code for my Java class.
I am using VS Code, with the Java Extension Pack installed, for Java Project Management.
Can someone please explain me step by step how is it possible to import the .jar library, in order to use the classes defined by my teacher.
I have tried to copy the .jar in the lib folder and then add the reference, but it still did not work. I also know that I have to declare the classpath, but when I create the Java Project the .classpath file is not created automatically.
Thanks already!
First you should examine the classes in .jar file. Then you should load that class as,
Class<?> c1 = Class.forName("java.lang.String");
Then after you can use that class by calling that Class reference type variable.
See this example as well,
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
// get the Class instance using forName method
Class c1 = Class.forName("java.lang.String");
System.out.print("Class represented by c1: "+ c1.toString());
} }
Try to understand the code and implement proper solution to your project.
Good Luck.

Maven Project class file not being found by eclipse

I have couple of maven projects let's say A & B. I have mvm installed them both before loading them inside eclipse.
One of the class in project A runs a class from project B. This class is trying to create a instance of a another class in B using the newInstance method.
Class clazz = Class.forName(className);
Constructor construct = clazz.getConstructor(new Class[] { String.class, ThreadFactory.class });
ResultClassFromB api = (ResultClassFromB) construct.newInstance(new Object[] {file, threadFactory });
I get InvocationTargetException for above code. On the surface, I understand eclipse can't find class file for ResultClassFromB. I've tried adding the parent folder of ResultClassFromB in the class path of project A but I still see the issue. How do I get past this?
info: file is mostly with comments.

Type A is already defined error

I tried to search for the solution, but what I found I don't know how to apply in this situation. Please help me correct my code.
package Exercise;
public class Ex11_11 {
public static void main(String[] args) {
A a = new A(3);
}
}
class A extends B { // type A is already defined, A has a red underline
public A (int t) {
System.out.println("A's constructor is invoked");
}
}
class B { // type B is already defined, B has a red underline
public B () {
System.out.println("B's constructor is invoked");
}
}
Eclipse sometimes gets confused. If you choose Clean from the Project menu, it might fix these errors.
Well, the first thing to check is obviously whether or not you have another class called A in your file or in the same package.
I had the same problem. My computer was restarted remotely by I.T, and Eclipse did not shut down gracefully. I noticed there was an extra java file in my project that I didn't add. Deleted it, and now the error is gone.
In Project-> Clean, select "Clean projects selected below", select my project(s) and check "Start a build immediately" with "Build only selected projects".
Then problem will resolve.
Check if all your class files are saved. I've had this problem a few times: i define a class in a class file then move it in it's own one. Java gets confised, because it reads from the old version of the original file. Once you save it with the missing class definition in it and define the class in the new file all should be ok.
In your project you might have test directory with the same package structure and the same class name (for example copied without changing class name to *Test).
If none of the above solutions worked for you then it possible that Build Path is messed up. When you add a src to the build path make sure the src is not in the exclusion list. Place *(wild card) in the inclusion list and nothing in the exclusion list.
Make sure
Project | Build Automatically
is checked.
The main reason for this is that somewhere in same package you have already defined a class with name A.
which causes type A is already defined error.
check if there is any subclass or inner class named A
Have you added another project to the build path?
I had the same issue on my development environment (Eclipse).
My Maven application consumed other applications. On Eclipse, those projects were just added to the build path. One of them had the same package structure and class filename. Eclipse ends up thinking both the files which are physically different are in the same directory since the package structure and filename are same.
For example, let's say there are two files as below:
/Users/uname/home/proj1/com/app/proj/main/java/util/file1.java
and
/Users/uname/home/proj2/com/app/proj/main/java/util/file1.java
and lets say both have the package name
com.app.define.proj.util
If you add one of the project to the other, Eclipse would consider both the files to be in the same location.
I resolved by creating a JAR file out of the consumed application, adding it to the build path and removing the Eclipse project from build path.
rename the class name A to Aa or something and try to run.

Double bind jar dependency

I have one Java project (Project A) in which I load other jars. These jars (Project B) all have one class implements an application interface. In order to know that interface, project b has to have project A as library.
Now, when starting project A, it loads the jar of project B, looks for the application class, gets the constructor and trys to create an object, but this fails:
The constructor from B's class creates an object implementing the interface which is known to project B, ALTHOUGH this is the same interface as in project A, but it seems that these two are not seen as being equal.
How can I solve this double bind dependency?
Edit:
This is how I try to create an application in project A:
clazz = Class.forName(className, true, loader);
ctor = (Constructor<? extends Application>) clazz.getConstructor();
Application app = ctor.newInstance();
The exception occurs in the third line where it says app is of type SpecificApplication (which is defined in the loaded jar and implements the Application interface) and thus cannot be cast to Application.
Put the interface in another jar, which is referenced by projects A and B.

Maven use resources from other modules?

how can I use resources from other maven modules? My goal is to provide a AbstractImportClass as well as the to be imported files in a specific maven module. And use this module within other modules extending this class.
Let's say ModuleA contains src/main/java/MyAbstractImportClass.java, and src/main/resources/MyImport.csv
I now want to use the abstract import class in ModuleB. Or rather, I will extend it, use the abstract-fileimport, and a few custom functions.
Then ModuleC also uses the abstracts' import and some custom functions.
The problem is: the import in abstract class goes with reader and InputStream. When I execute just ModuleA everything is fine.
But when I tried to include the module via maven pom, and then extend the module to call the import, then I get NullPointerException at the line where the reader is used.
So obvious I cannot use foreign module resources this way.
But how could I instead make use of this?
Update:
Module A:
src/main/java/path/to/MyClassA.java
src/main/resources/path/to/test.txt
abstract class MyClassA {
public static String TESTFILE = test.txt;
List<String> doImport(String filename) {
InputStream fileStream = resourceClass.getResourceAsStream(filename);
//some precessing
return list;
}
}
Module B:
src/main/java/path/to/MyClassB.java
class MyClassB implements MyClassA {
List<String> list = doImport(TESTFILE);
}
If I put MyClassB in same dir as A, then everything works fine.
If I build B in a own module I get NullPointer for InputStream, what means the file is not found.
I don't think your problem is related to Maven at all. Class.getResourceAsStream() resolves relative paths as relative to the class object that you call it on. Therefore, if you use that method in an abstract class, every subclass of it could be looking for the resource in a different place.
For example, given three classes:
Super:
package com.foo;
public class Super {
{ System.out.println(getClass().getResourceAsStream("test.properties")); }
}
Sub1, a subclass of Super:
package com.foo.bar;
import com.foo.Super;
public class Sub1 extends Super {}
Sub2, another subclass:
package com.foo.bar.baz;
import com.foo.Super;
public class Sub2 extends Super {}
If you create a Super, it'll look for the classpath resource "/com/foo/test.properties" because that's how the path "test.properties" resolves relative to the class com.foo.Super. If you create a Sub1, it'll look instead in "/com/foo/bar/test.properties", and for a Sub2 instance, it'll look in "/com/foo/bar/baz/test.properties".
You might want to use an absolute path to the resource instead of a relative one, or else have the subclasses specify paths relative to themselves. It depends on your design and what kind of abstraction you're trying to achieve.
It's not exactly clear what your code does. Could you provide sample of how you're reading resource? If you do it properly - by getting InputStream from resource file in classpath there should be no problem. You can start by checking that ModuleA.jar has your resource file inside.
You should check:
Module B depend on Module A in pom.xml
The passed in 'filename' parameter starts with a '/', that is to say, the 'filename' parameter is '/path/to/test.txt' other than 'path/to/test.txt'
You program should work if these two conditions is satisfield.

Categories

Resources