繁体   English   中英

Spring 请求处理失败; 嵌套异常是 java.lang.NoSuchMethodException:

[英]Spring Request processing failed; nested exception is java.lang.NoSuchMethodException:

I'm trying to load my postgresql db's table information not using traditional spring mvc pattern but also use java compiler function to make class into internal project directory & reload whole project that System can Recognize new class & method

当我在这个机制中使用简单的计算 class 时,它可以工作(仅用于测试)

但是当我交替使用我为加载数据库(DAO,SERVICE)设置的方法时

系统无法读取我的方法

这是错误代码

12월 02, 2020 3:29:57 오후 org.apache.catalina.core.StandardWrapperValve invoke
심각: 경로 [/inspect]의 컨텍스트 내의 서블릿 [dispatcher]을(를) 위한 Servlet.service() 호출이, 근본 원인(root cause)과 함께, 예외 [Request processing failed; nested exception is java.lang.NoSuchMethodException: kr.com.inspect.rule.Test.getMemberList(kr.com.inspect.service.impl.MemberServiceImpl)]을(를) 발생시켰습니다.
java.lang.NoSuchMethodException: kr.com.inspect.rule.Test.getMemberList(kr.com.inspect.service.impl.MemberServiceImpl)
    at java.base/java.lang.Class.getMethod(Class.java:2108)
    at kr.com.inspect.rule.RuleCompiler.runObject(RuleCompiler.java:127)
    at kr.com.inspect.controller.PostgreController.testRun(PostgreController.java:185)

当然,我正在搜索这种错误情况

  1. 在编译状态系统可以读取你的方法,但是当它试图读取方法时,它不起作用

  2. 参数可以是这个问题的Issue


在情况 1. 我在物理上划分创建 function 并在 controller 中运行 function 的功能。

在情况 2. 代表 Test 的方法具有与 MemberServiceImpl.getMemberList 相同的参数(列表)

请不要问我你为什么做傻事。 这就是我在这里的原因。

很抱歉我的英语很差

请帮忙

我制作的更多课程信息

Controller

    /**
     * 클래스 파일 생성
     * @return 디렉토리 값 반환
     * @throws Exception 예외 처리
     */
    @PostMapping("/xlsxDir")
    @ResponseBody
    public String xlsxDir () throws Exception{
        RuleCompiler test = new RuleCompiler();

        System.out.println("button clicked");
        // report 패키지의 TestRuleCompiler 클래스를 호출하는 테스트 소스
        String str ="\t\tTestRuleCompiler testRuleCompiler = new TestRuleCompiler();\n" +
                "\t\tint result = testRuleCompiler.Test(list);\n" +
                "\t\treturn result;\n";
        // jsonLogs 읽어오는 소스
//      String str ="\t\tList<Metadata> jsonLogs = postgreService.getMetadata();\n\t\tSystem.out.println(jsonLogs.get(0));\n\t\tSystem.out.println(\"success\");";
        // java 파일 컴파일 후 class 로드하는 메서드 호출

        //Object obj = 
        test.create(str, memberService);
        return "true";
    }
    
    /**
     * 클래스 파일 실행
     * @return 디렉토리 값 반환
     * @throws Exception 예외 처리
     */
    @PostMapping("/testRun")
    @ResponseBody
    public String testRun () throws Exception{
        RuleCompiler rc = new RuleCompiler();

        System.out.println("button clicked");
        
        Test test = new Test();
        // Test.class 안의 runMethod 메서드 실행하는 메서드 호출
        List<Member> rst = rc.runObject(test, memberService);
        System.out.println("result : " + rst);
        return "true";
    }

class TestRuleCompiler

package kr.com.inspect.report;

import java.util.List;

import kr.com.inspect.dao.MemberDao;
import kr.com.inspect.dto.Member;

public class TestRuleCompiler {
    
    public MemberDao memberDao;
    
    public int Test(int[] list){
        int result = 0;
        for(int i : list)
            result = result + i;
        return result;
    }
    
    public List<Member> getMemberList() {
        List<Member> list = memberDao.getMemberList();
        return list;
    }
}

class 规则编译器

package kr.com.inspect.rule;

import edu.emory.mathcs.backport.java.util.Arrays;
import kr.com.inspect.dto.Member;
import kr.com.inspect.service.MemberService;
import kr.com.inspect.service.PostgreService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.tools.*;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

@Component
public class RuleCompiler extends Thread {
    
    public static final Logger logger = LoggerFactory.getLogger(RuleCompiler.class);
    
    // 자바파일 생성하고 컴파일후 class 파일 로드해오는 파일 (이 메서드는 잘 작동됩니다.)
    public Object create(String body, MemberService memberService)throws Exception{
        String path = "/home/namuhwang/Documents/GitHub/spring-db-connect/src/main/java/";
        String classPath = "/home/namuhwang/Documents/GitHub/spring-db-connect/target/classes/";

        // Source를 만들고 Java파일 생성
        File sourceFile = new File(path+"kr/com/inspect/rule/Test.java");
        String source = this.getSource(body);
        new FileWriter(sourceFile).append(source).close();

        // java파일 컴파일 할때 옵션주기
        List<String> optionList = new ArrayList<>();
        // CLASS PATH 추가
        optionList.add("-classpath");
        optionList.add(System.getProperty("java.class.path")+":"+classPath);
//        optionList.add(System.getProperty("java.class.path"));
        // CLASS 파일 저장할 디렉토리
        optionList.add("-d");
        optionList.add(classPath);

        // 만들어진 Java 파일을 컴파일
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

        List<String> sources = Arrays.asList(new String[] {path+"kr/com/inspect/rule/Test.java"});

        DiagnosticCollector<JavaFileObject> diagnostic = new DiagnosticCollector<JavaFileObject>();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostic, null, null);
        Iterable<? extends JavaFileObject> compilationUnit
                = fileManager.getJavaFileObjectsFromStrings(sources);
        System.out.println("before Compile");
        JavaCompiler.CompilationTask task = compiler.getTask(
                null,
                fileManager,
                diagnostic,
                optionList,
                null,
                compilationUnit
        );
        Boolean success = task.call();
        System.out.println("after Compile");

        // 기본 comiler run하는 코드 (추후에 삭제 예정)
//        compiler.run(null, System.out, System.out, path+"kr/com/inspect/rule/Test.java");


        System.out.println("before Load");
        // 컴파일된 Class를 Load
        URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] {new File(classPath).toURI().toURL()});
//        Class<?> cls = Class.forName("kr.com.inspect.rule.Test", true, classLoader);
        Class<?> cls = classLoader.loadClass("kr.com.inspect.rule.Test");
        System.out.println("after Load");

        // Load한 Class의 Instance를 생성
        return cls.newInstance();
//        return (Object)true;
    }


    public String getSource(String body) {
        StringBuffer sb = new StringBuffer();

        // Java Source를 생성한다.
        // report 패키지의 TestRuleCompiler 클래스를 호출하는 테스트 소스
        sb.append("package kr.com.inspect.rule;\n"+
                "import kr.com.inspect.report.TestRuleCompiler;\n"+
                "public class Test { \n"+
                "public int runMethod(int[] list) {\n")
                .append(body)
                .append("\t}\n}");
        // jsonLog 읽어오는 소스
//        sb.append("package kr.com.inspect.rule;\n"+
//                "import kr.com.inspect.service.PostgreService;\n" +
//                "import kr.com.inspect.dto.Metadata;\n"+
//                "import java.util.List;\n"+
//                "public class Test { \n"+
//                "\tpublic void runMethod(PostgreService postgreService) throws Exception {\n")
//                .append(body)
//                .append("\t}\n}");
        return sb.toString();
    }

    // Test.class 안의 runMethod 메서드 실행
    @SuppressWarnings("unchecked")
    public List<Member> runObject(Object obj, MemberService memberService) throws Exception{
        //int[] list = {1, 2, 3};
        logger.debug("d",obj);
        logger.warn("w",obj);
        logger.error("e",obj);
        logger.info("i",obj);
        logger.trace("t",obj);
        System.out.println(memberService);
        System.out.println(obj);
        Class<?> arguments[] = new Class[]{memberService.getClass()}; //postgreService
        System.out.println(arguments);
        logger.debug("d",obj);
        logger.warn("w",obj);
        logger.error("e",obj);
        logger.info("i",obj);
        logger.trace("t",obj);
        // Source를 만들때 지정한 Method를 실행
        // runMethod 메소드 지정 
        Method objMethod = obj.getClass().getMethod("getMemberList", arguments);
          // 인자로 list를 보냄
        Object result = objMethod.invoke(obj, memberService);

        // postgreService 가 인자로 보내져야 하는데 보내지질 않음
        System.out.println("before Method");
        System.out.println(obj);
        System.out.println(memberService);
          // 문제 부분 (여기서 실행이 멈춤)
        logger.debug("d",obj);
        logger.warn("w",obj);
        logger.error("e",obj);
        logger.info("i",obj);
        logger.trace("t",obj);
        //Method objMethod = obj.getClass().getMethod("runMethod", arguments);
        logger.debug("d",obj);
        logger.warn("w",obj);
        logger.error("e",obj);
        logger.info("i",obj);
        logger.trace("t",obj);
        System.out.println(objMethod);
        System.out.println("after Method");
        System.out.println(obj);
        System.out.println(memberService);
        logger.debug("d",obj);
        logger.warn("w",obj);
        logger.error("e",obj);
        logger.info("i",obj);
        logger.trace("t",obj);
        //Object result = objMethod.invoke(obj, postgreService);
        logger.debug("d",obj);
        logger.warn("w",obj);
        logger.error("e",obj);
        logger.info("i",obj);
        logger.trace("t",obj);
        System.out.println(result);
        System.out.println("after invoke");
        return (List<Member>) result;
    }
}

class 测试

package kr.com.inspect.rule;


import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import kr.com.inspect.dto.Member;
import kr.com.inspect.report.TestRuleCompiler;
import kr.com.inspect.service.impl.MemberServiceImpl;
public class Test { 
    
    
    public MemberServiceImpl memberServiceimpl;
    
    public int runMethod01(int[] list) {
    
        TestRuleCompiler testRuleCompiler = new TestRuleCompiler();
        
        int result = testRuleCompiler.Test(list);
        return result;
    }
    
    public List<Member> getMemberList() {
        
        TestRuleCompiler testRuleCompiler = new TestRuleCompiler();
        
        List<Member> result = testRuleCompiler.getMemberList();
        return result;
    }
}

好吧,如果您跳过编译时检查并重新实现轮子,您会遇到其他情况下不会遇到的问题。

你的代码

Method objMethod = obj.getClass().getMethod("getMemberList", arguments);
Object result = objMethod.invoke(obj, memberService);

正在调用Test类型的objgetMemberListTestpublic List<Member> getMemberList()方法没有参数,因此您可能不应该将memberService作为参数传递,顺便提一下,异常中也提到了这一点( java.lang.NoSuchMethodException: kr.com.inspect.rule.Test.getMemberList(kr.com.inspect.service.impl.MemberServiceImpl)) ):

Method objMethod = obj.getClass().getMethod("getMemberList");
Object result = objMethod.invoke(obj);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM