当前位置: 首页 > 知识库问答 >
问题:

Spring 4升级后未加载应用程序上下文

唐和洽
2023-03-14

我正在将webapp中使用的spring框架版本从3.1.4升级到4.1.8。在新的Spring版本中,我们的一些单元测试失败了,因为@AutoWired不再工作。这是失败的测试之一:

@ContextConfiguration(locations={"/math-application-context.xml"})
public class MathematicaMathServiceTest extends JavaMathServiceTest{

@Autowired
private KernelLinkPool mathematicalKernelPool; 

protected static String originalServiceType = System.getProperty("calculation.math.service.type");

@AfterClass
public static void unsetMathServiceType(){
    System.clearProperty("calculation.math.service.type");

}

@BeforeClass
public static void setMathServiceType(){
    System.setProperty("calculation.math.service.type","Mathematica");
}

@Test
public void testMathematicaService() throws Exception{          


    try {           

        acquireKernelAndExecute(0);

        Assert.assertEquals(0, mathematicalKernelPool.getBorrowingThreadsCount());

    } catch(UnsatisfiedLinkError e) {
        System.out.println("Mathematica not installed. Skipping test");
    }catch(Exception ex){
        if (!ExceptionFormatter.hasCause(ex, MathServiceNotConfiguredException.class)){throw ex;}
        if (System.getProperty(MathService.SERVICE_CONFIGURED_SYSTEM_VARIABLE) != null){
            throw ex;
        }
        logger.error("Cannot execute test. Math service is not configured");
    }
}

}

public class KernelLinkPool extends GenericObjectPool implements InitializingBean{

private static final int RETRY_TIMEOUT_MS = 5000;

private static final long STARTUP_WAIT_TIME_MS = 10000;

private boolean mathematicaConfigured = true;
private PoolableObjectFactory factory;
// ensures that multiple requests from the same thread will be given the same KernelLink object
private static ThreadLocal<KernelLink> threadBoundKernel = new ThreadLocal<KernelLink>();
// holds the number of requests issued on each thread
private static ThreadLocal<Integer> callDepth = new ThreadLocal<Integer>();
private long maxBorrowWait;
private Integer maxKernels;
private boolean releaseLicenseOnReturn;
private Logger logger = LoggerFactory.getLogger(this.getClass());
// (used only for unit testing at this point)
private Map<String,Integer> borrowingThreads = new ConcurrentHashMap<String,Integer>();

public KernelLinkPool(PoolableObjectFactory factory) {
    super(factory);     
    this.factory = factory;
    this.setMaxWait(maxBorrowWait);

}

@Override
public Object borrowObject() throws Exception{
    return borrowObject(this.maxBorrowWait);
}

public Object borrowObject(long waitTime) throws Exception {
    long starttime = System.currentTimeMillis();

    if (!mathematicaConfigured){
        throw new MathServiceNotConfiguredException();
    }

    try{
        if (callDepth.get() == null){
            callDepth.set(1);
        }else{
            callDepth.set(callDepth.get()+1);
        }

        KernelLink link = null;         
        if (threadBoundKernel.get() != null){
            link = threadBoundKernel.get();
        }else{
            //obtain kernelLink from object pool
            //retry when borrowObject fail until
            //maxBorrowWait is reached
            while(true){
                try{
                    logger.debug("Borrowing MathKernel from object pool");
                    link = (KernelLink) super.borrowObject();
                    break;
                }catch(KernelLinkCreationException ex){
                    long timeElapsed = System.currentTimeMillis() - starttime;
                    logger.info("Failed to borrow MathKernel. Time elapsed [" + timeElapsed + "] ms", ex);
                    if(timeElapsed >= waitTime){
                        logger.info("Retry timeout reached");
                        throw ex;
                    }
                    Thread.sleep(RETRY_TIMEOUT_MS);
                }
            }
            logger.debug("borrowed [" + link + "]");
            threadBoundKernel.set(link);
        }

        borrowingThreads.put(Thread.currentThread().getName(),callDepth.get());

        return link;

    }catch(Exception ex){
        logger.error("Failed to acquire Mathematica kernel. Borrowing threads [" + borrowingThreads + "]");
        throw ex;
    }
}


public void returnObject(Object obj) throws Exception {

    callDepth.set(callDepth.get()-1);

    if (callDepth.get() <= 0){
        threadBoundKernel.set(null);

        borrowingThreads.remove(Thread.currentThread().getName());

        if (releaseLicenseOnReturn){
            // will destroy obj
            super.invalidateObject(obj);
        }
        else{
            // will park obj in the pool of idle objects
            super.returnObject(obj);
        }
    }else{
        borrowingThreads.put(Thread.currentThread().getName(),callDepth.get());
    }

}


@Override
public void afterPropertiesSet() throws Exception {

    try{

        if (maxKernels == 0){
            List<KernelLink> links = new ArrayList<KernelLink>();
            while (true){
                try{
                    links.add((KernelLink)factory.makeObject());
                }catch(KernelLinkCreationException ex){
                    break;
                }
            }       
            if(links.isEmpty()){
                logger.warn("No available Mathematica license!");
                mathematicaConfigured = false;
                return;
            }
            for (KernelLink link : links){
                factory.destroyObject(link);
            }
            logger.info("Detected number of available Mathematica license = [" + links.size() + "]");
            setMaxActive(links.size());
            setMaxIdle(links.size());
        }else{
            if(maxKernels < 0){
                logger.info("Set number of Mathematica license to no limit");
            }else{
                logger.info("Set number of Mathematica license to [" + maxKernels + "]");
            }
            setMaxActive(maxKernels);
            setMaxIdle(maxKernels);         
        }

        Object ob = borrowObject(STARTUP_WAIT_TIME_MS);
        returnObject(ob);                   

        mathematicaConfigured = true;
    }catch(Throwable ex){
        logger.warn("Mathematica kernel pool could not be configured: ", ex.getMessage());
        mathematicaConfigured = false;
    }
}


public int getBorrowingThreadsCount() {
    return borrowingThreads.size();
}

public Integer getMaxKernels() {
    return maxKernels;
}

public void setMaxKernels(Integer maxKernels) {
    this.maxKernels = maxKernels;
}

public boolean isMathematicaConfigured(){
    return mathematicaConfigured;
}

public boolean isReleaseLicenseOnReturn() {
    return releaseLicenseOnReturn;
}

public void setReleaseLicenseOnReturn(boolean releaseLicenseOnReturn) {
    this.releaseLicenseOnReturn = releaseLicenseOnReturn;
}

public long getMaxBorrowWait() {
    return maxBorrowWait;
}

public void setMaxBorrowWait(long maxBorrowWait) {
    this.maxBorrowWait = maxBorrowWait;
}       
}
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.etse.math.wolfram.KernelLinkPool] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

这是math-application-context文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

<beans profile="unitTest,integratedTest,activeServer">
    <bean class="org.springframework.jmx.export.MBeanExporter"
        lazy-init="false">
        <property name="registrationBehaviorName" value="REGISTRATION_IGNORE_EXISTING" />
        <property name="beans">
            <map>
                <entry key="etse.math:name=MathematicalKernelFactory"
                    value-ref="mathematicalKernelFactory" />
                <entry key="etse.math:name=MathematicalKernelPool" value-ref="mathematicalKernelPool" />
            </map>
        </property>
    </bean>

    <bean id="mathService" class="com.etse.math.MathServiceFactoryBean">
        <property name="mathServiceType" value="${calculation.math.service.type}"/>
        <property name="mathematicaService" ref="mathematicaService"/>
    </bean> 

    <bean id="mathematicaService" class="com.etse.math.wolfram.MathematicaService">
        <property name="kernelPool" ref="mathematicalKernelPool" />
        <property name="minParallelizationSize" value="${calculation.mathematica.kernel.parallel.batch.size}" />
    </bean>

    <bean id="mathematicalKernelPool" class="com.etse.math.wolfram.KernelLinkPool"
        destroy-method="close">
        <constructor-arg ref="mathematicalKernelFactory" />
        <property name="maxKernels" value="${calculation.mathematica.max.kernels}" />
        <property name="maxBorrowWait"
            value="${calculation.mathematica.kernel.borrow.max.wait}" />
        <property name="releaseLicenseOnReturn"
            value="${calculation.mathematica.kernel.release.license.on.return}" />
    </bean>

    <bean id="mathematicalKernelFactory" class="com.etse.math.wolfram.KernelLinkFactory">
        <property name="debugPackets" value="false" />
        <property name="linkMode" value="launch" />
        <property name="mathematicaKernelLocation" value="${calculation.mathematica.kernel.location}" />
        <property name="mathematicaLibraryLocation" value="${calculation.mathematica.library.location}" />
        <property name="mathematicaAddOnsDirectory" value="${calculation.mathematica.addons.directory}" />
        <property name="linkProtocol" value="sharedMemory" />
    </bean>
</beans>

<beans profile="passiveServer,thickClient,tools">
        <bean id="mathService" class="com.etse.math.DummyMathService"/>
</beans>

我还尝试使用应用程序上下文加载bean,但失败了,出现了以下异常:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'mathematicalKernelPool' is defined

如果删除autowired字段,测试将失败,并且通过超类中的应用程序上下文加载的另一个bean(mathService)会出现NoSuchBeanDefinitionException。因此,似乎由于某种原因没有加载math-application-context中的应用程序上下文。知道这里会发生什么吗?谢谢你。

更新:

我查看了应用程序上下文中定义的bean,并确认math-application-context中定义的bean都不存在。应用程序上下文只包含在超类加载的另一个上下文文件中定义的bean。为什么它不能加载Math-Application-Context?

共有1个答案

席言
2023-03-14

在这一点上,我将诚实地摆脱XML配置,转而完全基于注释/代码。创建一个Config类,并让它创建任何需要自动连线的bean。

 类似资料:
  • 嗨,我正试图让spring junit测试用例...我要求加载完整的应用程序上下文。但是,junit测试不会初始化完整的应用程序上下文。 因此,它应该扫描com.test包中的所有spring bean,并将它们加载到Junit TestCase的applicationcontext中。但从大豆的产量来看,它似乎没有做到这一点。

  • 我刚刚在Hostgator上购买了主机,构建了一个本地symfony项目,并将其上传到服务器上,但我无法完成部署,因为symfony需要PHP5.6,而我有5.4。 因此,我使用cPanel并通过php配置菜单将php版本更新为5.6。它说它更新了,但我的仍然告诉我我使用的是PHP5.4。唉,如果我通过ssh运行或,它仍然显示为PHP5.4。 我做错了什么?

  • 问题内容: 我有一个包含2个测试的测试类: 当我单独运行测试时,我不会出错,但是当我同时运行所有测试时,会失败。失败是由于某些测试修改了应用程序上下文导致的: 是否可以单独运行此测试?我只想在启动test1时读取所有必需的东西,然后运行测试,然后关闭所有必需的东西。然后启动test2。 问题答案: 您可以在修改应用程序上下文的测试类上使用@DirtiesContext批注。 Java文档 Spri

  • 我正在处理一个Spring Boot应用程序,其中我使用该应用程序公开SOAP WebService。我在Spring boot应用程序中使用Apache CFX framework for SOAP impl。我正在使用基于注释的方法。 我在一个bean中的Spring Boot配置文件中设置应用程序上下文时遇到了问题。下面是我的代码。 配置文件如下所示。 现在我有了bean SOAPproce

  • 我在我的Android应用程序中使用滑翔进行图像加载,以避免任何崩溃,我正在加载带有应用程序上下文的图像。这会对应用程序和内存的性能产生什么影响?

  • 问题内容: 从1.8升级到django 1.9时,出现此错误。我检查了类似问题的答案,但我认为这不是任何第三方软件包或应用程序的问题。 我已经为“ django.contrib.auth”修改了已安装的应用程序。 问题答案: 尝试将以下行添加到设置文件的顶部: 并且如果这不能帮助你尝试从已安装的应用程序列表中逐一删除第三方应用程序。