3

My ServiceLoader dont want to load my new service. I think I have everything correctly setted up.

Core.Main

public class Main {
  public static void main(String[] args) {
      System.out.println("Before");
      Iterator<IService> services = ServiceLoader.load(IService.class).iterator();
      while (services.hasNext()) {
          IService service = services.next();
          System.out.println(service.sayHi());
      }
      System.out.println("After");
  }
}

Core.service.IService

package service;

public interface IService {
    String sayHi();
}

DbDataBuilder.builder.DbDataBuilder

package builder;

import service.IService;
public class DbDataBuilder implements IService {

    public DbDataBuilder() {
    }

    public String sayHi() {
        return "I am Data Builder";
    }
 }

META-INF/services/service.Iservice

builder.DbDataBuilder

Project structure

But when I run it, console output is:

Before
After

Do I something wrong?

medy75
  • 652
  • 11
  • 33
  • 1
    Does it work when calling the service directly? If not you probably have a classpath problem. – Thomas Oct 06 '16 at 11:20
  • I dont know how to do it, cause DbDataBuilder needs dependency to Core (Iservice interface) and if I want to call DbDataBuilder from Core, I would need DBDataBuilder dependency in it, but its a cyclic dependency and it dont want to compile. So Im not able to call it directly. – medy75 Oct 06 '16 at 11:29
  • Did you try with a simple implementation as the one you posted? Note that such cyclic dependencies are not that much of a problem if you compile the classes in one go. It might be that the service loader just doesn't see the service hence the test with a direct call. – Thomas Oct 06 '16 at 11:55
  • 2
    Add to Main.java the following line: `Class.forName("builder.DbDataBuilder")` I expect you will get ClassNotFoundException and it will be a proof that builder is not visible on classpath, so cannot be found by ServiceLoader – michaldo Oct 06 '16 at 12:08
  • Yes, it throws ClassNotFoundException. How can I fix it? – medy75 Oct 06 '16 at 12:14
  • But if I got DbDataBuilder in classpath, then ServiceLoader doesnt make sense, right? – medy75 Oct 06 '16 at 12:41
  • 1
    ServiceLoader is useful when builder is on classpath at runtime, not at compile time. You should add third module with compile scope dependency to `Core` and runtime scope dependency to `DbDataBuilder`, move `Main` to the third module and enjoy ServiceLoader features – michaldo Oct 06 '16 at 12:58
  • It works. Thank you very much! – medy75 Oct 07 '16 at 09:33
  • @michaldo You help me too. You should get this comment as a answer so you could get you proper upvotes! Thanks.. – Josemy Apr 26 '18 at 10:03

1 Answers1

1

ServiceLoader is useful when builder is on classpath at runtime, not at compile time. You should add third module with compile scope dependency to Core and runtime scope dependency to DbDataBuilder, move Main to the third module and enjoy ServiceLoader features

michaldo
  • 4,195
  • 1
  • 39
  • 65