Ошибка обработки запроса Spring; вложенным исключением является java.lang.Исключение NoSuchMethodException:

#java #spring #exception

#java #spring #исключение

Вопрос:

Я пытаюсь загрузить postgresql информацию о таблице моей базы данных, не используя традиционный шаблон spring mvc, но также использую java compiler функцию для создания класса во внутреннем каталоге проекта и перезагрузки всего проекта, чтобы система могла распознать новый класс и метод

Когда я использую простой вычислительный класс в этом механизме, он работает (только для тестирования)

Но когда я альтернативно использую метод, который я настроил для загрузки БД (DAO, SERVICE),

система не может прочитать мой метод

Вот код ошибки

 1202, 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. Параметр может быть причиной этой проблемы

В случае 1. Я физически разделяю функции, которые создают функцию и запускают функцию в контроллере.

В случае 2. Метод, который обозначает Test, имеет тот же параметр (список), что и MemberServiceImpl.getMemberList

пожалуйста, не спрашивайте меня, почему вы делаете глупости. Вот почему я здесь.

Мне жаль, что мой английский плохой

Пожалуйста, помогите

Дополнительная информация о классах, которую я сделал

Контроллер

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

        System.out.println("button clicked");
        // report 패키지의 TestRuleCompiler 클래스를 호출하는 테스트 소스
        String str ="ttTestRuleCompiler testRuleCompiler = new TestRuleCompiler();n"  
                "ttint result = testRuleCompiler.Test(list);n"  
                "ttreturn resu<n";
        // jsonLogs 읽어오는 소스
//      String str ="ttList<Metadata> jsonLogs = postgreService.getMetadata();nttSystem.out.println(jsonLogs.get(0));nttSystem.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";
    }
 

класс 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 resu<
    }
    
    public List<Member> getMemberList() {
        List<Member> list = memberDao.getMemberList();
        return list;
    }
}

 

компилятор правил класса

 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>) resu<
    }
}

 

тест класса

 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 resu<
    }
    
    public List<Member> getMemberList() {
        
        TestRuleCompiler testRuleCompiler = new TestRuleCompiler();
        
        List<Member> result = testRuleCompiler.getMemberList();
        return resu<
    }
}
 

Ответ №1:

Что ж, если вы пропустите проверки во время компиляции и повторно реализуете wheel, вы столкнетесь с проблемами, которых у вас не было бы в противном случае.

Ваш код

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

вызывается getMemberList тип obj , который имеет тип Test , но public List<Member> getMemberList() метод Test не имеет параметров, поэтому, вероятно, вам не следует передавать memberService в качестве параметра, который, кстати, также упоминается в exception ( 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);
 

Комментарии:

1. Спасибо, но я попробовал ваше решение и перезапустил проект, все равно получаю ту же ошибку; (

2. Итак, вы вызываете obj.getClass().getMethod без arguments , но все равно получаете сообщение об ошибке, что метод с параметрами не найден?

3. на самом деле я действительно не знаю, что это проблема с параметрами? или проблема с аннотациями и компонентами? но, согласно истории журнала, система продолжает говорить, что не может найти метод

4. Что вы не понимаете в «методе тестирования public List<Member> getMemberList() не имеет параметров, поэтому, вероятно, вам не следует передавать MemberService в качестве параметра»? В вашем коде буквально говорится: «Дайте мне метод getMemberList с параметром типа MemberService», а Java говорит: «В Test нет такого метода», что, очевидно, верно.

5. Мой коллега и я решаем эту проблему, используя параметры класса, чтобы система могла считывать имена методов thx для ответа на мой вопрос