java - Spring does not discover @RequestMapping annotation for a new context at runtime -


i tried develop plugin system spring boot web application. application deployed on tomcat server using root context path. plugin system allows me load specially prepared jar files @ runtime. system should able undeploy plugins @ runtime. jars contained inside plugin folder in current working dir. wanted every plugin have it's own spring context operate with. dependency injection working expected spring not discover @requestmapping annotation plugin context. question is: how can make spring discover @requestmapping annotations plugins (at runtime)?

i using latest spring boot version , following application.yml:

# server server:   error:     whitelabel:       enabled: true   session:     persistent: true   tomcat:     uri-encoding: utf-8 # spring spring:   application:     name: plugins   mvc:     favicon:       enabled: false   favicon:     enabled: false   thymeleaf:     encoding: utf-8 # logging logging:   file: application.log   level.: error 

this code loads plugin:

annotationconfigapplicationcontext context = new annotationconfigapplicationcontext(); urlclassloader urlclassloader = urlclassloader.newinstance(new url[] { plugin.getpluginurl() }, getclass().getclassloader()); // plugin.getpluginurl refer jar file plugin code (see below). context.setclassloader(urlclassloader); context.setparent(applicationcontext); // applicationcontext the context of original spring application. autowired. classpathbeandefinitionscanner scanner = new classpathbeandefinitionscanner(context, true); scanner.scan("my.plugin.package"); context.refresh(); 

and controller code (inside plugin):

@controller public class plugintestcontroller {     @postconstruct     private void postcontruct() {         system.out.println("controller ready.");     }      @requestmapping(value = "/test", method = requestmethod.get)     public responseentity<string> doget() {         return new responseentity<>("hello!", httpstatus.ok);     } } 

when start application , load plugin can see "controller ready." in console. when try access url (localhost:8080/test) see 404 error page. every url of non plugin spring context controllers gets mapped correctly (i can access localhost:8080/index example). found out have requestmappinghandlermapping. dont understand how make use of in order make annotation work again.

edit: found way make @requestmapping annotation work controller using following code:

// context plugins context, created earlier. (map.entry < string, object > bean: context.getbeanswithannotation(controller.class).entryset()) {     object obj = bean.getvalue();     // http://stackoverflow.com/questions/27929965/find-method-level-custom-annotation-in-a-spring-context     // using aop check aop proxying. if proxying spring cglib (not via spring aop)     // use org.springframework.cglib.proxy.proxy#isproxyclass detect proxy if proxying using jdk     // proxy use java.lang.reflect.proxy#isproxyclass     class < ? > objclz = obj.getclass();     if (org.springframework.aop.support.aoputils.isaopproxy(obj)) {         objclz = org.springframework.aop.support.aoputils.gettargetclass(obj);     }     (method m: objclz.getdeclaredmethods()) {         if (m.isannotationpresent(requestmapping.class)) {             requestmapping requestmapping = annotatedelementutils.findmergedannotation(m, requestmapping.class);             requestmappinginfo requestmappinginfo = requestmappinginfo                 .paths(requestmapping.path())                 .methods(requestmapping.method())                 .params(requestmapping.params())                 .headers(requestmapping.headers())                 .consumes(requestmapping.consumes())                 .produces(requestmapping.produces())                 .mappingname(requestmapping.name())                 .customcondition(null)                 .build();             // register actual mapping, controller can handle request             requestmappinghandlermapping.registermapping(requestmappinginfo, obj, m);         }     } } 

however still searching way make work using spring way: https://github.com/spring-projects/spring-framework/blob/fb7ae010c867ae48ab51f48cce97fe2c07f44115/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/abstracthandlermethodmapping.java

thanks reading.

the springmvc has it's own cache of @requestmapping, detail code requestmappinghandlermapping. can see, init method shown, maybe can call init method after load new plugin.

protected void inithandlermethods() {         if (logger.isdebugenabled()) {             logger.debug("looking request mappings in application context: " + getapplicationcontext());         }          string[] beannames = (this.detecthandlermethodsinancestorcontexts ?                 beanfactoryutils.beannamesfortypeincludingancestors(getapplicationcontext(), object.class) :                 getapplicationcontext().getbeannamesfortype(object.class));          (string beanname : beannames) {             if (ishandler(getapplicationcontext().gettype(beanname))){                 detecthandlermethods(beanname);             }         }         handlermethodsinitialized(gethandlermethods());     } 

this spring3's requestmappinghandlermapping code, maybe there changes in spring4's impl.


Comments

Popular posts from this blog

java - SSE Emitter : Manage timeouts and complete() -

jquery - uncaught exception: DataTables Editor - remote hosting of code not allowed -

java - How to resolve error - package com.squareup.okhttp3 doesn't exist? -