簡體   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