justify icon indicating copy to clipboard operation
justify copied to clipboard

Json validation provider not found

Open anitadc opened this issue 5 years ago • 12 comments

I am facing same problem when running Spring boot application jar from command prompt. But It is working fine from eclipse and same application jar in other machine. I am using java11 and no module structure.

Originally posted by @anitadc in https://github.com/leadpony/justify/issues/18#issuecomment-560415481

anitadc avatar Dec 02 '19 14:12 anitadc

@anitadc Thank you for contacting me. Are you using Spring Boot Maven Plugin in your build?

leadpony avatar Dec 02 '19 21:12 leadpony

Yes. I am using spring-boot-maven-plugin 2.1.2

anitadc avatar Dec 03 '19 09:12 anitadc

@anitadc Thank you for your reply. I ported the code sample Basic Parser to a Spring Boot application. Please find the attatched project. justify-examples-spring-boot.zip It seems to work fine. Please tell me if there exists difference from your project.

leadpony avatar Dec 03 '19 13:12 leadpony

Difference is - I am calling this justify parser asynchronously using completablefuture and external executor

anitadc avatar Dec 05 '19 02:12 anitadc

Can you provide me with a sample project that reproduces the reported problem?

leadpony avatar Dec 05 '19 13:12 leadpony

To generate issue, initialize JsonValidationService within child thread instead of static or Singleton object.

Do below changes In your sample project - https://github.com/leadpony/justify/files/3916858/justify-examples-spring-boot.zip

CompletableFuture.runAsync(()-> { JsonValidationService service = JsonValidationService.newInstance() ; ....... validate(arg1[0], arg2[1]); ..... }) .exceptionally((Throwable e)-> LOG.error(e); return null; });

anitadc avatar Dec 06 '19 07:12 anitadc

Thank you @anitadc With your help, I reproduced the problem finally using both spring-boot-maven-plugin and CompletableFuture. However the same problem occurs even without Justify. Could you please run the following code?

@SpringBootApplication
public class Application implements CommandLineRunner {

    private static final Logger LOG = LoggerFactory.getLogger(Application.class);

    @Override
    public void run(String... args) throws Exception {
        var future = CompletableFuture.runAsync(() -> {
            JsonProvider provider = loadProvider();
            LOG.info(provider.getClass().getName());
        }).exceptionally(e -> {
            LOG.error(e.getMessage());
            return null;
        });
        future.get();
    }

    private JsonProvider loadProvider() {
        ServiceLoader<JsonProvider> loader = ServiceLoader.load(JsonProvider.class);
        Iterator<JsonProvider> it = loader.iterator();
        if (it.hasNext()) {
            return it.next();
        } else {
            throw new IllegalStateException("No service provider found");
        }
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

pom.xml (with Justify removed)

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>jakarta.json</groupId>
            <artifactId>jakarta.json-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>jakarta.json</artifactId>
            <classifier>module</classifier>
            <version>${jakarta.json.version}</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

Therefore this is NOT a problem of Justify. I suspect that the problem is due to a restriction or bug of spring-boot-maven-plugin using with ServiceLoader class.

leadpony avatar Dec 08 '19 09:12 leadpony

I added a fallback logic to JsonValidationService#newInstance(). Could you please test with the current snapshot? See Building from Source section in the top page of this repository.

leadpony avatar Dec 09 '19 22:12 leadpony

Thank you @anitadc With your help, I reproduced the problem finally using both spring-boot-maven-plugin and CompletableFuture. However the same problem occurs even without Justify. Could you please run the following code?

@SpringBootApplication
public class Application implements CommandLineRunner {

    private static final Logger LOG = LoggerFactory.getLogger(Application.class);

    @Override
    public void run(String... args) throws Exception {
        var future = CompletableFuture.runAsync(() -> {
            JsonProvider provider = loadProvider();
            LOG.info(provider.getClass().getName());
        }).exceptionally(e -> {
            LOG.error(e.getMessage());
            return null;
        });
        future.get();
    }

    private JsonProvider loadProvider() {
        ServiceLoader<JsonProvider> loader = ServiceLoader.load(JsonProvider.class);
        Iterator<JsonProvider> it = loader.iterator();
        if (it.hasNext()) {
            return it.next();
        } else {
            throw new IllegalStateException("No service provider found");
        }
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

pom.xml (with Justify removed)

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>jakarta.json</groupId>
            <artifactId>jakarta.json-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>jakarta.json</artifactId>
            <classifier>module</classifier>
            <version>${jakarta.json.version}</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

Therefore this is NOT a problem of Justify. I suspect that the problem is due to a restriction or bug of spring-boot-maven-plugin using with ServiceLoader class.

Correct. This will happen with any code like justify which will use ServiceLoader and current thread classloader.

anitadc avatar Dec 10 '19 06:12 anitadc

I added a fallback logic to JsonValidationService#newInstance(). Could you please test with the current snapshot? See Building from Source section in the top page of this repository.

I appreciate this change. Hopefully this will work. I will confirm you.

anitadc avatar Dec 10 '19 06:12 anitadc

Did you add this fallback logic in 2.1.0 version?? Kindly publish this in maven repository.

anitadc avatar Dec 10 '19 08:12 anitadc

@anitadc You need to build and install it to your local repository by yourself. If it works well with your application, I will publish it as the next official release. Please follow the instruction in the section Building from Source. You also need to change the version of the dependency in your pom.xml to 2.1.0-SNAPSHOT Thank you for your cooperation.

leadpony avatar Dec 10 '19 12:12 leadpony