简体   繁体   中英

“Hello World” with Java annotations

Problem description: Compile 2 jar files independently, without having to include each other on classpath; and at runtime, include both and invoke main() in one jar to print a string on stdout. Parts of the output string have to come from the 2nd jar.

Constraints: The solution cannot be IDE-dependent or use any other jar files.

Answering what have I done so far: My Solution is described below.

Reason to ask the question: I am trying to figure out if/how to use annotations to solve this problem (hopefully in a more elegant manner), but cannot find any suitable documentation or tutorial. I appreciate any pointer(s) for that also.

My Solution: A batch file (on Unix, please change the backslash to forward slash, semicolon to colon and the rem's to #) as follows:

rem Compile and package the testing class (Main) without any library
javac -d target core\*.java
cd target
jar cvf ..\main.jar .\core
cd ..

rem Compile and package the Greeting and Greeted classes as a library
javac -d lib impl\*.java
cd lib
jar cvf ..\mylib.jar .\impl
cd ..

rem Use the two parts above at runtime and execute main() in Main class
java -cp main.jar;mylib.jar core.Main

There are 2 files in the impl directory and 2 in the core, as follows:

/* File: impl/Greeting.java */

package impl;

public class Greeting {
    public String getGreeting () {
        return "Hello";
}}

/* File: impl/Greeted.java */

package impl;

public class Greeted {
    public String getGreeted () {
        return "world";
}

/* File: core/Main.java */

package core;

public class Main {

    private String  greeting = "Learn annotations",     greeted = "keep using Java",

            // Can read the following 4 values from a configuration file, too
            // Trying to see if we can get these using Java annotations

            greetingClassName = "impl.Greeting",    greetingMethod = "getGreeting",
            greetedClassName = "impl.Greeted",  greetedMethod = "getGreeted";

    public Main () {
        try {
            MyRunTime runTime = new MyRunTime();

            Object gting = runTime.getInstance(greetingClassName),
                gted  = runTime.getInstance(greetedClassName),

                g1Str = runTime.getResponseNoArg (gting, greetingMethod),
                g2Str = runTime.getResponseNoArg (gted, greetedMethod);

            if (g1Str instanceof String)    greeting = (String) g1Str;
            if (g2Str instanceof String)    greeted = (String) g2Str;
        } catch (Exception ex) {
            System.err.println ("Error in Library loading: " + ex.getMessage());
    }}

    public void greet () {
        System.out.println (greeting + ", " + greeted + "!");
    }

    public static void main (String[] args) {
        new Main().greet();
}}

/* File: core/MyRunTime.java */

package core;

import  java.lang.reflect.*;

public  class  MyRunTime {

    public Object getResponseNoArg (Object anInstance, String methodName) throws
                    NoSuchMethodException,
                        IllegalAccessException,
                        InvocationTargetException {
        Method method = anInstance.getClass().getMethod (methodName);
        return method.invoke (anInstance);
    }

    public Object getInstance (String className) throws 
                    ClassNotFoundException,
                    InstantiationException,
                    IllegalAccessException {
            Class c = Class.forName (className);
            return c.newInstance();
    }
}

That's it. I would also like not to mess with the ClassLoader unless absolutely necessary. Once I get a handle on how to do this with annotations, I can look into passing arguments and go forward. Thank you for your help.

I wouldn't use Annotations for this - it's probably worth covering what Annotations are and where they are best used.

Instead I would do something like:

  • Place different files in each jar
  • A main class to each jar file, which does the same thing: list the files on the classpath

I think that would meet the project requirements.

To list the files on the classpath you could so something like:

public class Main {
  public static void main(final String[] args) throws java.lang.Throwable {
    final String list = System.getProperty( "java.class.path" );
    for (String path : list.split( ";" )) {
      java.io.File object = new java.io.File( path );
      if ( object.isDirectory() )
        for ( String entry : object.list() ) { 
          java.io.File thing = new java.io.File( entry );
          if ( thing.isFile() )
            System.out.println( thing );
          else if( object.isFile() )
            System.out.println( object );
        }
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM