5

I have a bunch of little services, conveniently called Microservices ;-), that all have the same startup behavior. They are arranged in packages - each one for one service. The package naming is like this:

com.foo.bar.Application

where com.foo is the domain part, bar is the actual service name and Application is my main instance class with the main method.

Now what I would like to do is print out a standardized log message when they are started, showing the URL a user may query to get some information on the service. Per definition the URL to get infos for the service shall be constructed like this:

   IP:PORT/bar/admin/info 

I tried to get this bar.name with getClass()... and the like, but that does not work. So I tried this:

LOG.info("Access URLs:\n----------------------------------------------------------\n" +
            "\tLocal: \t\thttp://127.0.0.1:{}/" + getMyClass() + "/info\n" +
            "\tExternal: \thttp://{}:{}/" + getMyClass() + "/info\n----------------------------------------------------------",
                env.getProperty("server.port"),
                InetAddress.getLocalHost().getHostAddress(),
                env.getProperty("server.port")
        );

 /**
     * Get the name of the application class as a static value, so we can show it in the log
     */
    public static final Class[] getClassContext() {
        return new SecurityManager() {
            protected Class[] getClassContext(){return super.getClassContext();}
        }.getClassContext();
    };
    public static final Class getMyClass() { return getClassContext()[2];}

But as you may already have guessed, this prints out far too much:

class com.foo.bar.Application

Where all I'd like to get is

bar

How can I achieve this???

By the way, I'm using Java 8 and Spring boot - if that helps

Best regards,

Chris

siliconchris
  • 613
  • 2
  • 9
  • 22

4 Answers4

8

You could try retrieving the package object from the class first, then reading its name. The following code will give you the full containing package name (such as "com.foo.bar") in the packageName variable, and the direct parent name (such as bar) in the directParent variable:

    String packageName = getMyClass().getPackage().getName();

    String directParent;
    if(packageName.contains(".")) {
        directParent = packageName.substring(1 + packageName.lastIndexOf("."));
    } else {
        directParent = packageName;
    }

So, your log statement could just use one of these variables if you put it after this snippet.

ernest_k
  • 44,416
  • 5
  • 53
  • 99
1

Something like this:

String pack = getClass().getPackage().getName();
String[] split = pack.split("\\.");
pack = split[split.length-1];
PeterMmm
  • 24,152
  • 13
  • 73
  • 111
  • 1
    [Class.getPackage](https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getPackage--) can return null. In which case, you just have to parse the fully qualified class name. – jmehrens May 23 '16 at 12:41
0

thanks to Ernest for his tip, it works flawlessly. For all others that may have the same requirement, I'll post my code below:

@ComponentScan(basePackages = "com.foo.fileexportservice")
@EnableAutoConfiguration(exclude = {MetricFilterAutoConfiguration.class, MetricRepositoryAutoConfiguration.class, LiquibaseAutoConfiguration.class})
@EnableEurekaClient
@EnableCircuitBreaker
@EnableFeignClients(basePackages = "com.foo.fileexportservice")
public class Application {

    private static final Logger LOG = LoggerFactory.getLogger(Application.class);
    private static final String ERROR_MSG = "You have misconfigured your application! ";

    @Inject
    private Environment env;

    /**
     * Main method, used to run the application.
     */
    public static void main(String[] args) throws UnknownHostException {
        SpringApplication app = new SpringApplication(Application.class);
        app.setShowBanner(true);
        SimpleCommandLinePropertySource source = new SimpleCommandLinePropertySource(args);
        addDefaultProfile(app, source);
        Environment env = app.run(args).getEnvironment();
        LOG.info("Access URLs:\n----------------------------------------------------------\n" +
            "\tLocal: \t\thttp://127.0.0.1:{}/" + getPackageName() + "/admin/info\n" +
            "\tExternal: \thttp://{}:{}/" + getPackageName() + "/admin/info\n----------------------------------------------------------",
                env.getProperty("server.port"),
                InetAddress.getLocalHost().getHostAddress(),
                env.getProperty("server.port")
        );

    }

    /**
     * Get the name of the application class as a static value, so we can show it in the log
     */
    private static final String getPackageName() {
        String packageName = getMyClass().getPackage().getName();

        String directParent;
        if(packageName.contains(".")) {
            directParent = packageName.substring(1 + packageName.lastIndexOf("."));
        } else {
            directParent = packageName;
        }
        return directParent;
    };
    private static final Class[] getClassContext() {
        return new SecurityManager() {
            protected Class[] getClassContext(){return super.getClassContext();}
        }.getClassContext();
    };
    private static final Class getMyClass() { return getClassContext()[2];}


    /**
     * If no profile has been configured, set by default the "dev" profile.
     */
    private static void addDefaultProfile(SpringApplication app, SimpleCommandLinePropertySource source) {
        if (!source.containsProperty("spring.profiles.active") &&
                !System.getenv().containsKey("SPRING_PROFILES_ACTIVE")) {

            app.setAdditionalProfiles(Constants.SPRING_PROFILE_DEVELOPMENT);
        }
    }
}
siliconchris
  • 613
  • 2
  • 9
  • 22
0

Since Java 9, there is a new method Class.getPackageName():

Returns the fully qualified package name.

Honza Zidek
  • 9,204
  • 4
  • 72
  • 118