[置顶] 如何解决SpringBoot与ODataJClient版本冲突的问题?

标签: SpringBootjackson-dataformat-xodatajclientODataV3
488人阅读 评论(0) 收藏 举报
分类:

我们知道使用SpringBoot可以帮助我们快速建立一个原型;笔者当前使用的SpringBoot的版本是1.4.3.RELESE. 当前使用的ODataJClient的版本是0.9.0. 如果SpringBoot和包含ODataJClient的单元测试分开跑,SpringBoot和ODataJClient都能通过Maven或者Gradle编译,也都能透过测试。 但是如果把SpringBoot和ODataJClient集成起来,就会出现下面的问题。报错的原因如下:

Caused by: java.util.ServiceConfigurationError: javax.xml.stream.XMLEventFactory: Provider com.fasterxml.aalto.stax.EventFactoryImpl not a subtype
at java.util.ServiceLoader.fail(ServiceLoader.java:239)
at java.util.ServiceLoader.access$300(ServiceLoader.java:185)
at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:376)
at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
at javax.xml.stream.FactoryFinder$1.run(FactoryFinder.java:353)
at java.security.AccessController.doPrivileged(Native Method)
at javax.xml.stream.FactoryFinder.findServiceProvider(FactoryFinder.java:341)
at javax.xml.stream.FactoryFinder.find(FactoryFinder.java:313)
at javax.xml.stream.FactoryFinder.find(FactoryFinder.java:227)
at javax.xml.stream.XMLEventFactory.newInstance(XMLEventFactory.java:64)
at org.hibernate.boot.jaxb.internal.MappingBinder.<init>(MappingBinder.java:40)
at org.hibernate.boot.spi.XmlMappingBinderAccess.<init>(XmlMappingBinderAccess.java:43)
at org.hibernate.boot.MetadataSources.<init>(MetadataSources.java:87)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:179)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:149)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:54)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1648)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1585)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:554)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:856)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:761)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:371)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:111)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189)
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)

通过下面的分析,可知

mvn dependency:tree -Dverbose

原来缺少jackson-dataformat-xml的依赖(其实不缺少,只不过是odatajclient-engine也依赖jackson-dataformat-xml(2.2.3),其版本比SpringBoot默认的版本低)

所以odatajclient-engine的覆盖了SpringBoot的jackson-dataformat-xml(2.8.5)的版本,从而报错。所以解决方案是显式的在SpringBoot的项目中加入下面的依赖。

<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>

<dependency>
<groupId>com.msopentech.odatajclient</groupId>
<artifactId>odatajclient-engine</artifactId>
<version>0.9.0</version>
</dependency> 

注意,其必须在加在odatajclient-engine的Maven或者Gradle依赖前面。这样SpringBoot抛出的上面异常就会消除。但是,还有坑。

这个时候SpringBoot的问题解决了,但是odatajclient调用oData V3(比如DSC 5.x的服务)的单元测试就会失败,

调用示范代码:

import java.io.InputStream;
import java.util.List;
import org.junit.Test;
import com.msopentech.odatajclient.engine.communication.request.retrieve.ODataEntitySetRequest;
import com.msopentech.odatajclient.engine.communication.request.retrieve.ODataRetrieveRequestFactory;
import com.msopentech.odatajclient.engine.communication.response.ODataRetrieveResponse;
import com.msopentech.odatajclient.engine.data.ODataEntity;
import com.msopentech.odatajclient.engine.data.ODataEntitySet;
import com.msopentech.odatajclient.engine.format.ODataPubFormat;
import com.msopentech.odatajclient.engine.uri.ODataURIBuilder;

public class ODataTest {
	String testODataServiceRootURL="http://dsc-pull-server:8080/PSDSCPullServer.svc/";
	@Test
	public void testName()  {
		ODataURIBuilder uriBuilder = new ODataURIBuilder(testODataServiceRootURL).appendEntityTypeSegment("Nodes(AgentId='19940477-E202-11E6-80B8-BE117D36B7A4')/Reports");

	    ODataEntitySetRequest req = ODataRetrieveRequestFactory.getEntitySetRequest(uriBuilder.build());
	    req.setFormat(ODataPubFormat.JSON);
	    req.getResponseTemplate();
	    ODataRetrieveResponse<ODataEntitySet> res = req.execute();
	    InputStream input=res.getRawResponse();
	    @SuppressWarnings("rawtypes")
	   // JsonSerializer jsonSerializer= new StdSerializer();
	    
       // System.out.println( res.getStatusCode());
        ODataEntitySet entitySet = res.getBody();
        List<ODataEntity> lsODataEntity=entitySet.getEntities();
        for(ODataEntity odataEntity:lsODataEntity){
        	odataEntity.getProperties();
        	
        }
        System.out.println(entitySet.getCount());
      
	   
	}
}

结果如下:

java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    com/msopentech/odatajclient/engine/data/Deserializer.toODataErrorFromXML(Ljava/io/InputStream;)Lcom/msopentech/odatajclient/engine/data/xml/XMLODataError; @22: invokespecial
  Reason:
    Type 'com/fasterxml/aalto/stax/OutputFactoryImpl' (current frame, stack[5]) is not assignable to 'com/msopentech/javax/xml/stream/XMLOutputFactory'
  Current Frame:
    bci: @22
    flags: { }
    locals: { 'java/io/InputStream' }
    stack: { uninitialized 0, uninitialized 0, uninitialized 4, uninitialized 4, 'com/fasterxml/aalto/stax/InputFactoryImpl', 'com/fasterxml/aalto/stax/OutputFactoryImpl' }
  Bytecode:
    0x0000000: bb00 0259 bb00 0359 bb00 0459 b700 05bb
    0x0000010: 0006 59b7 0007 b700 08bb 0009 59b7 000a
    0x0000020: b700 0b4c 2b2a 1300 5bb6 0010 c000 5bb0
    0x0000030: 4cbb 0012 5912 5c2b b700 14bf          
  Exception Handler Table:
    bci [0, 47] => handler: 48
  Stackmap Table:
    same_locals_1_stack_item_frame(@48,Object[#116])


at com.msopentech.odatajclient.engine.data.ODataReader.readEntitySet(ODataReader.java:63)
at com.msopentech.odatajclient.engine.communication.request.retrieve.ODataEntitySetRequest$ODataEntitySetResponseImpl.getBody(ODataEntitySetRequest.java:89)
at com.msopentech.odatajclient.engine.communication.request.retrieve.ODataEntitySetRequest$ODataEntitySetResponseImpl.getBody(ODataEntitySetRequest.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

很奇怪的输出,原因是新加的jackson-dataformat-xml版本,覆盖了odatajclient-engine中依赖的版本(因为SpringBoot中的jackson-dataformat-xml是高版本,会自动覆盖odatajclient-engine所依赖的低版本)。

那么解决方案是什么?解决方式就是重新编译odatajclient-engine的jar包,把其依赖的jackson-dataformat-xml的版本改成最新的版本,在重新编译。在odatajclient-engine-xml项目中,修改jackson-dataformat-xml的版本为2.8.5,与SpringBoot的1.4.3-RLEASE版本保持一致。

<?xml version="1.0" encoding="UTF-8"?>
<!--

    Copyright © Microsoft Open Technologies, Inc.

    All Rights Reserved

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
    OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
    ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A
    PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.

    See the Apache License, Version 2.0 for the specific language
    governing permissions and limitations under the License.

-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>com.msopentech.odatajclient</groupId>
    <artifactId>odatajclient</artifactId>
    <version>0.9.1-SNAPSHOT</version>
  </parent>

  <name>Client OData library for Java: Engine XML parser</name>
  <description>Java client API for OData 3.0 services: Engine XML parser</description>
  <groupId>com.msopentech.odatajclient</groupId>
  <artifactId>odatajclient-engine-xml</artifactId>
  <packaging>jar</packaging>
  
  <properties>
    <main.basedir>${project.parent.basedir}</main.basedir>
  </properties>

  <dependencies>
    <dependency>
      <groupId>com.fasterxml.jackson.dataformat</groupId>
      <artifactId>jackson-dataformat-xml</artifactId>
      <version>2.8.5</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml</groupId>
      <artifactId>aalto-xml</artifactId>
    </dependency>
  </dependencies>

  <build>
    <plugins>
    
    </plugins>
    
    <resources>
      <resource>
        <directory>..</directory>
        <targetPath>META-INF</targetPath>
        <includes>
          <include>LICENSE</include>
        </includes>
      </resource>
    </resources>
  </build>
  
</project>

然后在SpringBoot中,加入对odatajclient-engine:0.9.1-SNAPSHOT(而不是0.9.0)版本的引用。则所有的问题都缝纫而解.





1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:382832次
    • 积分:6302
    • 等级:
    • 排名:第4080名
    • 原创:219篇
    • 转载:0篇
    • 译文:5篇
    • 评论:157条
    博客专栏