spring-attic / spring-native

Spring Native is now superseded by Spring Boot 3 official native support
https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html
Apache License 2.0
2.74k stars 355 forks source link

Failed to handle bean with name&Multiple privileged packages #1402

Closed A001007008 closed 2 years ago

A001007008 commented 2 years ago

I'm try to use spring-native with some old project which complete by springboot (version:2.2.9) and springcould (version:Hoxton.SR8). According to the documentation ,I upgrade springboot(2.2.9->2.6.2) and springcould(Hoxton.SR8->2021.0.0). After adapting to the new version, it runs normally(Non-native mode)

Try to run mvn -Pnative-image package -X

org.springframework.aot.context.bootstrap.generator.BeanDefinitionGenerationException: Failed to handle bean with name 'menuController' and type 'com.xxx.xxx.xxx.xxx.controller.MenuController'
    at org.springframework.aot.context.bootstrap.generator.ApplicationContextAotProcessor.writeBeanDefinitions(ApplicationContextAotProcessor.java:136)
    at org.springframework.aot.context.bootstrap.generator.ApplicationContextAotProcessor.bootstrapMethod(ApplicationContextAotProcessor.java:103)
    at org.springframework.aot.context.bootstrap.generator.ApplicationContextAotProcessor.process(ApplicationContextAotProcessor.java:95)
    at org.springframework.aot.build.ContextBootstrapContributor.contribute(ContextBootstrapContributor.java:80)
    at org.springframework.aot.build.BootstrapCodeGenerator.generate(BootstrapCodeGenerator.java:91)
    at org.springframework.aot.build.BootstrapCodeGenerator.generate(BootstrapCodeGenerator.java:71)
    at org.springframework.aot.build.GenerateBootstrapCommand.call(GenerateBootstrapCommand.java:107)
    at org.springframework.aot.build.GenerateBootstrapCommand.call(GenerateBootstrapCommand.java:42)
    at picocli.CommandLine.executeUserObject(CommandLine.java:1953)
    at picocli.CommandLine.access$1300(CommandLine.java:145)
    at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2352)
    at picocli.CommandLine$RunLast.handle(CommandLine.java:2346)
    at picocli.CommandLine$RunLast.handle(CommandLine.java:2311)
    at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2179)
    at picocli.CommandLine.execute(CommandLine.java:2078)
    at org.springframework.aot.build.GenerateBootstrapCommand.main(GenerateBootstrapCommand.java:112)
Caused by: java.lang.IllegalStateException: Multiple privileged packages: [com.xxx.xxx.xxx.base.controller, com.xxx.xxx.xxx.auth.controller]
    at org.springframework.aot.context.bootstrap.generator.infrastructure.ProtectedAccessAnalysis.getPrivilegedPackageName(ProtectedAccessAnalysis.java:57)
    at org.springframework.aot.context.bootstrap.generator.bean.DefaultBeanRegistrationWriter.writeBeanRegistration(DefaultBeanRegistrationWriter.java:104)
    at org.springframework.aot.context.bootstrap.generator.ApplicationContextAotProcessor.writeBeanDefinitions(ApplicationContextAotProcessor.java:128)
    ... 15 more
[ERROR] 
org.apache.maven.plugin.MojoExecutionException: Could not exec java
    at org.springframework.aot.maven.AbstractBootstrapMojo.forkJvm (AbstractBootstrapMojo.java:187)
    at org.springframework.aot.maven.GenerateMojo.execute (GenerateMojo.java:128)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
    at org.codehaus.classworlds.Launcher.main (Launcher.java:47)
Caused by: org.apache.maven.plugin.MojoExecutionException: Bootstrap code generator finished with exit code: 1
    at org.springframework.aot.maven.AbstractBootstrapMojo.forkJvm (AbstractBootstrapMojo.java:184)
    at org.springframework.aot.maven.GenerateMojo.execute (GenerateMojo.java:128)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
    at org.codehaus.classworlds.Launcher.main (Launcher.java:47)

env:

Java -version:
openjdk version "11.0.13" 2021-10-19
OpenJDK Runtime Environment GraalVM CE 21.3.0 (build 11.0.13+7-jvmci-21.3-b05)
OpenJDK 64-Bit Server VM GraalVM CE 21.3.0 (build 11.0.13+7-jvmci-21.3-b05, mixed mode, sharing)
mvn -v:
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: .
Java version: 11.0.13, vendor: GraalVM Community, runtime: \graalvm-ce-java11-21.3.0
Default locale: zh_CN, platform encoding: UTF-8
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
snicoll commented 2 years ago

Thanks for the report. MenuController seems to be package private and require a package private component from another package. Sharing the code of MenuController can help us figure out why.

A001007008 commented 2 years ago

Here is MenuControllerInformation(Excerpts from different types of code):


import xxxx.xxxx.xxxx.biz.auth.model.Menu;
import xxxx.xxxx.xxxx.biz.auth.repository.MenuRepository;
import xxxx.xxxx.xxxx.biz.auth.service.MenuImportService;
import xxxx.xxxx.xxxx.biz.auth.service.MenuService;
import xxxx.xxxx.xxxx.framework.base.controller.CrudBaseController;
import xxxx.xxxx.xxxx.framework.swagger.ApiMs;
import xxxx.xxxx.xxxx.util.web.ResponseResult;
import xxxx.xxxx.xxxx.util.web.ResponseResult2;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

@Api(tags = "xx")
@Scope("prototype")
@Controller
@RequestMapping("/menu")
public class MenuController extends CrudBaseController<Menu, MenuRepository> {
    @Autowired
    private MenuImportService menuImportService;

    @RequestMapping("/listPage")
    public String listPage(Map<String, Object> model) {

        return "biz/auth/menu_list";
    }

    @RequestMapping("/getTreeData")
    @ResponseBody
    public Object getTreeData(HttpServletRequest request) {
        try {
            return ResponseResult.getReturnResult(request, ((MenuService) service).getTreeData(request));
        } catch (Exception e) {
            return ResponseResult.getReturnResultError(request, e);
        }
    }

     @ApiMs
    @ApiOperation(value = "xxxxx")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "lstMenu", value = "xx", required = false, dataType = "List<Menu>", paramType = "body")
    })
    @RequestMapping(value = "/v1/saveMenus", method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<ResponseResult2<List<Menu>>> saveMenus(@RequestBody List<Menu> lstMenu) {
        return ResponseResult2.getReturnResult(((MenuService) service).saveMenus(lstMenu));
    }

   //Omit the same definition
}

Here is CrudBaseController&&ResponseResult&&ApiMsInformation(Excerpts from different types of code):

public class CrudBaseController<T, R extends JpaRepository<T, Long>> {
    @Autowired
    protected CrudBaseService<T, R> service;
   @RequestMapping(
        value = {"/save"},
        produces = {"application/json;charset=UTF-8"}
    )
    @ResponseBody
    public Object save(HttpServletRequest request) {
        try {
            return ResponseResult.getReturnResult(request, this.service.saveOrUpdate(request));
        } catch (Exception var3) {
            return ResponseResult.getReturnResultError(request, var3);
        }
    }
    //Omit the same definition
}

public class ResponseResult {
     public static Object getReturnResult(Object data) {
        ResponseResult responseResult = new ResponseResult(data);
        return responseResult;
    }

    public static Object getReturnResultError(HttpServletRequest request, Exception e) {
        if (e instanceof InfoTipException) {
            logger.info(e.getMessage(), e.getMessage());
        } else {
            logger.error(e.getMessage(), e);
        }

        ResponseResult responseResult = new ResponseResult("");
        responseResult.setMsg(e.getMessage());
        responseResult.setSuccess(false);
        responseResult.setCode("500");
        return responseResult;
    }
}

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiMs {
}

Ps: All type of Controller&&Service all defined like(maybe it has some problem?):

XXXXController exdents CrudBaseController<Entity,Repository>{}
XXXXService exdents CrudBaseService<Entity,Repository>{}
snicoll commented 2 years ago

Yes, I believe that CrudBaseController is injecting a package private component, maybe CrudBaseService? What AOT reveals here is that it is impossible to configure your application without resorting to reflection privileged access in multiple packages. This is a problem on its own as it means you can't instantiate such a component in a unit test.

There's not much we can do at this point. Can you please review what's package private and maybe restructure so that you can instantiate menu controller from a unit test?

A001007008 commented 2 years ago

Problem solved,thanks

snicoll commented 2 years ago

Thanks for following-up.

Dave-he commented 2 years ago

I use spring-native 0.11.2-SNAPSHOT to package , result also is :Failed to handle bean with name&Multiple privileged packages. @Service public class AppSceneService extends BaseService<AppSceneDO, Long> {}

public class BaseService<T, K> {

snicoll commented 2 years ago

@Dave-he please follow-up on what was said above already. There is a linked issue that updated the documentation. If that didn't help, please let us know why so that we can update the phrasing if necessary.

Dave-he commented 2 years ago

I use the mybatis-plus, autoware the service, package that not work : ` public abstract class BaseService<M extends BaseMapper, T> extends ServiceImpl<M, T> implements IService { }

public interface IMailRecordDbCmd { }

@Service public class MailRecordDbCmdImpl extends BaseService<IMailRecordMapper, MailRecordEntity> implements IMailRecordDbCmd { }

@Service public class A { @Autowired public IMailRecordDbCmd mailRecordCmdService; }

`

org.springframework.aot.context.bootstrap.generator.BeanDefinitionGenerationException: Failed to handle bean with name 'mailRecordDbCmdImpl' and type 'com.demo.service.MailRecordDbCmdImpl' at org.springframework.aot.context.bootstrap.generator.ApplicationContextAotProcessor.writeBeanDefinitions(ApplicationContextAotProcessor.java:138) at org.springframework.aot.context.bootstrap.generator.ApplicationContextAotProcessor.bootstrapMethod(ApplicationContextAotProcessor.java:104) at org.springframework.aot.context.bootstrap.generator.ApplicationContextAotProcessor.process(ApplicationContextAotProcessor.java:96) at org.springframework.aot.build.ContextBootstrapContributor.contribute(ContextBootstrapContributor.java:80) at org.springframework.aot.build.BootstrapCodeGenerator.generate(BootstrapCodeGenerator.java:91) at org.springframework.aot.build.BootstrapCodeGenerator.generate(BootstrapCodeGenerator.java:71) at org.springframework.aot.build.GenerateBootstrapCommand.call(GenerateBootstrapCommand.java:107) at org.springframework.aot.build.GenerateBootstrapCommand.call(GenerateBootstrapCommand.java:42) at picocli.CommandLine.executeUserObject(CommandLine.java:1953) at picocli.CommandLine.access$1300(CommandLine.java:145) at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2352) at picocli.CommandLine$RunLast.handle(CommandLine.java:2346) at picocli.CommandLine$RunLast.handle(CommandLine.java:2311) at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2179) at picocli.CommandLine.execute(CommandLine.java:2078) at org.springframework.aot.build.GenerateBootstrapCommand.main(GenerateBootstrapCommand.java:112) Caused by: java.lang.IllegalStateException: Multiple privileged packages: [com.baomidou.mybatisplus.extension.service.impl, com.demo.service.mail] at org.springframework.aot.context.bootstrap.generator.infrastructure.ProtectedAccessAnalysis.getPrivilegedPackageName(ProtectedAccessAnalysis.java:57) at org.springframework.aot.context.bootstrap.generator.bean.DefaultBeanRegistrationWriter.writeBeanRegistration(DefaultBeanRegistrationWriter.java:104) at org.springframework.aot.context.bootstrap.generator.ApplicationContextAotProcessor.writeBeanDefinitions(ApplicationContextAotProcessor.java:130) ... 15 more

snicoll commented 2 years ago

@Dave-he Thanks but there's nothing we can do about that. Please report this against mybatis-plus or stop using package-private injection in MailRecordDbCmdImpl.