JHipster is a development platform to quickly generate, develop, & deploy modern web applications & microservice architectures using Spring-boot framework. Jhipster has “straight to go” script to deploy on google cloud.
Optaplanner is an AI library which helps solve planning and scheduling problems.
My goal is to use Jhipster to develop quickly a platform which resort to optaplanner to solve a specific problem, and finally deploy the code on Google Kubernate. I finally come with a solution by merging examples codes from Optaplanner and Jhipster.
As shown in the folowing output, it works well on my machine on local.After installing Jhipster :
jhipster mvn package -Pprod jib:dockerBuild java -jar target/jhipster-0.0.1-SNAPSHOT.jar
██╗ ██╗ ██╗ ████████╗ ███████╗ ██████╗ ████████╗ ████████╗ ███████╗ ██║ ██║ ██║ ╚══██╔══╝ ██╔═══██╗ ██╔════╝ ╚══██╔══╝ ██╔═════╝ ██╔═══██╗ ██║ ████████║ ██║ ███████╔╝ ╚█████╗ ██║ ██████╗ ███████╔╝ ██╗ ██║ ██╔═══██║ ██║ ██╔════╝ ╚═══██╗ ██║ ██╔═══╝ ██╔══██║ ╚██████╔╝ ██║ ██║ ████████╗ ██║ ██████╔╝ ██║ ████████╗ ██║ ╚██╗ ╚═════╝ ╚═╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═╝
:: JHipster 🤓 :: Running Spring Boot 2.5.4 :: :: https://www.jhipster.tech :: 23:14:22.340 INFO [main ] The following profiles are active: prod 23:14:25.183 INFO [main ] Web application configuration, using profiles: prod 23:14:25.184 INFO [main ] Web application fully configured 23:14:31.135 DEBUG [main ] Identified candidate component class: URL [jar:file:/home/parfait/Programming/JavaScript/Jhipster/target/jhipster-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/com/mycompany/myapp/domain/TimeTable.class] 23:14:31.145 DEBUG [main ] Identified candidate component class: URL [jar:file:/home/parfait/Programming/JavaScript/Jhipster/target/jhipster-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/com/mycompany/myapp/domain/Lesson.class] 23:14:35.403 INFO [main ] JBoss Threads version 3.1.0.Final 23:14:35.477 INFO [main ] Started JhipsterApp in 14.484 seconds (JVM running for 15.042) 23:14:35.479 INFO [main ] ---------------------------------------------------------- Application 'Jhipster' is running! Access URLs: Local: http://localhost:8080/ External: http://127.0.1.1:8080/ Profile(s): [prod] ----------------------------------------------------------
But when I execute the script to deploy the same code on Google Kuberntes, I face the following error:
jhipster k8s ./mvnw clean compile jib:build ./mvnw -ntp -Pprod jib:build -Djib.to.image=gcr.io/jhipster17/jhipster bash kubectl-apply.sh -f
Output from Kubernetes logs:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'timeTableResource' defined in file [/app/classes/com/mycompany/myapp/web/rest/TimeTableResource.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'solverManager' defined in class path resource [org/optaplanner/spring/boot/autoconfigure/OptaPlannerAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.optaplanner.core.api.solver.SolverManager]: Factory method 'solverManager' threw exception; nested exception is java.lang.NullPointerException at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1354) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) at com.mycompany.myapp.JhipsterApp.main(JhipsterApp.java:69) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'solverManager' defined in class path resource [org/optaplanner/spring/boot/autoconfigure/OptaPlannerAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.optaplanner.core.api.solver.SolverManager]: Factory method 'solverManager' threw exception; nested exception is java.lang.NullPointerException at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1380) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ... 17 common frames omitted Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.optaplanner.core.api.solver.SolverManager]: Factory method 'solverManager' threw exception; nested exception is java.lang.NullPointerException at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ... 31 common frames omitted Caused by: java.lang.NullPointerException: null at java.compiler@11.0.12/javax.tools.ToolProvider.lambda$matches$0(Unknown Source) at java.base/java.security.AccessController.doPrivileged(Native Method) at java.compiler@11.0.12/javax.tools.ToolProvider.matches(Unknown Source) at java.compiler@11.0.12/javax.tools.ToolProvider.getSystemTool(Unknown Source) at java.compiler@11.0.12/javax.tools.ToolProvider.getSystemJavaCompiler(Unknown Source) at org.kie.memorycompiler.jdknative.NativeJavaCompiler.compile(NativeJavaCompiler.java:73) at org.kie.memorycompiler.AbstractJavaCompiler.compile(AbstractJavaCompiler.java:41) at org.kie.memorycompiler.KieMemoryCompiler.compileNoLoad(KieMemoryCompiler.java:129) at org.kie.memorycompiler.KieMemoryCompiler.compileNoLoad(KieMemoryCompiler.java:101) at org.kie.memorycompiler.KieMemoryCompiler.compile(KieMemoryCompiler.java:53) at org.kie.memorycompiler.KieMemoryCompiler.compile(KieMemoryCompiler.java:39) at org.drools.ancompiler.KieBaseUpdaterANC.inMemoryUpdate(KieBaseUpdaterANC.java:66) at org.drools.ancompiler.KieBaseUpdaterANC.run(KieBaseUpdaterANC.java:52) at org.drools.ancompiler.KieBaseUpdaterANC.generateAndSetInMemoryANC(KieBaseUpdaterANC.java:99) at org.optaplanner.core.impl.score.director.stream.DroolsConstraintStreamScoreDirectorFactory.buildKieBaseFromModel(DroolsConstraintStreamScoreDirectorFactory.java:115) at org.optaplanner.core.impl.score.director.stream.DroolsConstraintStreamScoreDirectorFactory.buildKieBase(DroolsConstraintStreamScoreDirectorFactory.java:104) at org.optaplanner.core.impl.score.director.stream.DroolsConstraintStreamScoreDirectorFactory.<init>(DroolsConstraintStreamScoreDirectorFactory.java:71) at org.optaplanner.core.impl.score.director.ScoreDirectorFactoryFactory.buildConstraintStreamScoreDirectorFactory(ScoreDirectorFactoryFactory.java:223) at org.optaplanner.core.impl.score.director.ScoreDirectorFactoryFactory.decideMultipleScoreDirectorFactories(ScoreDirectorFactoryFactory.java:103) at org.optaplanner.core.impl.score.director.ScoreDirectorFactoryFactory.buildScoreDirectorFactory(ScoreDirectorFactoryFactory.java:71) at org.optaplanner.core.impl.solver.DefaultSolverFactory.buildScoreDirectorFactory(DefaultSolverFactory.java:116) at org.optaplanner.core.impl.solver.DefaultSolverFactory.buildSolver(DefaultSolverFactory.java:83) at org.optaplanner.core.impl.solver.DefaultSolverManager.validateSolverFactory(DefaultSolverManager.java:68) at org.optaplanner.core.impl.solver.DefaultSolverManager.<init>(DefaultSolverManager.java:57) at org.optaplanner.core.api.solver.SolverManager.create(SolverManager.java:111) at org.optaplanner.spring.boot.autoconfigure.OptaPlannerAutoConfiguration.solverManager(OptaPlannerAutoConfiguration.java:98) at org.optaplanner.spring.boot.autoconfigure.OptaPlannerAutoConfiguration$$EnhancerBySpringCGLIB$$2e4db969.CGLIB$solverManager$3(<generated>) at org.optaplanner.spring.boot.autoconfigure.OptaPlannerAutoConfiguration$$EnhancerBySpringCGLIB$$2e4db969$$FastClassBySpringCGLIB$$277961ad.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) at org.optaplanner.spring.boot.autoconfigure.OptaPlannerAutoConfiguration$$EnhancerBySpringCGLIB$$2e4db969.solverManager(<generated>) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ... 32 common frames omitted
This is the code for the SolverManager bean injection, based on the Jhipster examples code:
@RestController @RequestMapping("/api") public class TimeTableResource { private TimeTableRepository timeTableRepository; private SolverManager<TimeTable, Long> solverManager; public TimeTableResource(TimeTableRepository timeTableRepository, SolverManager<TimeTable, Long> solverManager) { this.timeTableRepository = timeTableRepository; this.solverManager = solverManager; } /** * {@code POST /solve} */ @PostMapping("/solve") public void solve(TimeTableRepository timeTableRepository, SolverManager<TimeTable, Long> solverManager) throws URISyntaxException { log.debug("REST request to solve "); solverManager.solveAndListen(TimeTableRepository.SINGLETON_TIME_TABLE_ID, timeTableRepository::findById, timeTableRepository::save); } }
The full code can be found here. I don’t understand why this “Unsatisfied dependency” happens when deployed on gke whereas there is no such error on local machine, nor on gce.
Can someone help me solve this?
Advertisement
Answer
There is a NullPointerException
lurking in the stack trace:
java.lang.NullPointerException: null at java.compiler@11.0.12/javax.tools.ToolProvider.lambda$matches$0(Unknown Source)
Having never seen this exception before, I can make an educated guess: could it be that you don’t have a Java compiler on the machine? Please install a full JDK (one that brings javac
as well as java
) and this problem may go away.
The reason for that is that Constraint Streams – in order to generate the code for your constraints – will need to compile some Java classes into bytecode. And without javac
, that is not possible.