JAXB 解组单元测试在 Eclipse 中成功,但在 gradle 测试中失败并显示“JAXB 无法处理接口”

问题描述 投票:0回答:1

这是一个单元测试,当我在 Eclipse 中运行它时可以成功运行,但当我使用 gradle 命令行“gradle test”运行它时会失败。

package com.mycompany.user;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class ImportUserTest {

    @Test
    public void testUnmarshall() throws Exception {
        ImportUser importUser = new ImportUser();
        UserList userList = importUser.unmarshall("src/test/resources/userList.xml");
        assertEquals("John Doe", userList.getUser().get(0).getFullName());
    }
}

ImportUser 类如下:

package com.mycompany.user;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

public class ImportUser {

    private static final String PACKAGE_CONTEXT = "com.mycompany.user";

    public UserList unmarshall(String inputFile) throws JAXBException, FileNotFoundException, ParserConfigurationException, SAXException {
        JAXBContext jc = JAXBContext.newInstance(PACKAGE_CONTEXT);
        Unmarshaller u = jc.createUnmarshaller();
        return (UserList) JAXBUtilities.safeUnmarshall(u, new FileInputStream(inputFile));
    }
}

这个JAXBUtilities类如下:

package com.mycompany.user;

import java.io.InputStream;
import java.io.Reader;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.sax.SAXSource;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class JAXBUtilities {

    private JAXBUtilities() {
    }

    public static Object safeUnmarshall(Unmarshaller u, InputStream in) throws ParserConfigurationException, SAXException, JAXBException {
        return safeUnmarshall(u, new InputSource(in));
    }

    public static Object safeUnmarshall(Unmarshaller u, Reader reader) throws ParserConfigurationException, SAXException, JAXBException {
        return safeUnmarshall(u, new InputSource(reader));
    }
    
    public static Object safeUnmarshall(Unmarshaller u, InputSource inputSource) throws ParserConfigurationException, SAXException, JAXBException {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setValidating(true);
        spf.setNamespaceAware(true);
        spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
        spf.setFeature("http://xml.org/sax/features/validation", false);
        spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
        spf.setXIncludeAware(false);

        Source xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(), inputSource);
        return u.unmarshal(xmlSource);
    }
}

XML 输入下方:

<userList>
  <user name="string">
    <fullName>John Doe</fullName>
    <description>BO user</description>
    <lastPropertyNum>3</lastPropertyNum>
    <loginIddleDays>3</loginIddleDays>
    <maxLoginAttempt>3</maxLoginAttempt>
    <maxTrades>3</maxTrades>
    <passwordCheckDigit>true</passwordCheckDigit>
    <passwordCheckSpecialChar>false</passwordCheckSpecialChar>
    <passwordMinLength>3</passwordMinLength>
    <passwordChangeDue>false</passwordChangeDue>
    <thresholdDays>3</thresholdDays>
    <updateUser>string</updateUser>
    <version>3</version>
    <processingOrg>ALL</processingOrg>
  </user>
</userList>

我从下面生成的类中删除了注释(由 JAXB 2.1.3 生成):

package com.mycompany.user;

import javax.xml.bind.annotation.XmlRegistry;

@XmlRegistry
public class ObjectFactory {

    public UserType createUserType() {
        return new UserTypeImpl();
    }

    public UserList createUserList() {
        return new UserListImpl();
    }
}
package com.mycompany.user;

import java.util.List;

public interface UserList {

    List<UserType> getUser();

}
package com.mycompany.user;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "user" })
@XmlRootElement(name = "userList")
public class UserListImpl implements UserList {

    @XmlElement(required = true, type = UserTypeImpl.class)
    protected List<UserType> user;

    @Override
    public List<UserType> getUser() {
        if (user == null) {
            user = new ArrayList<>();
        }
        return user;
    }

}
package com.mycompany.user;

import java.util.List;

public interface UserType {
    String getFullName();
    void setFullName(String value);
    String getDescription();
    void setDescription(String value);
    Integer getLastPropertyNum();
    void setLastPropertyNum(Integer value);
    Integer getLoginIddleDays();
    void setLoginIddleDays(Integer value);
    Integer getMaxLoginAttempt();
    void setMaxLoginAttempt(Integer value);
    Integer getMaxTrades();
    void setMaxTrades(Integer value);
    Boolean isPasswordCheckDigit();
    void setPasswordCheckDigit(Boolean value);
    Boolean isPasswordCheckSpecialChar();
    void setPasswordCheckSpecialChar(Boolean value);
    Integer getPasswordMinLength();
    void setPasswordMinLength(Integer value);
    Boolean isPasswordChangeDue();
    void setPasswordChangeDue(Boolean value);
    Integer getThresholdDays();
    void setThresholdDays(Integer value);
    String getUpdateUser();
    void setUpdateUser(String value);
    Integer getVersion();
    void setVersion(Integer value);
    List<String> getProcessingOrg();
    String getName();
    void setName(String value);
}
package com.mycompany.user;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "userType", propOrder = { "fullName", "description", "lastPropertyNum", "loginIddleDays",
        "maxLoginAttempt", "maxTrades", "passwordCheckDigit", "passwordCheckSpecialChar", "passwordMinLength",
        "passwordChangeDue", "thresholdDays", "updateUser", "version", "processingOrg" })
public class UserTypeImpl implements UserType {

    protected String fullName;
    protected String description;
    protected Integer lastPropertyNum;
    protected Integer loginIddleDays;
    protected Integer maxLoginAttempt;
    protected Integer maxTrades;
    protected Boolean passwordCheckDigit;
    protected Boolean passwordCheckSpecialChar;
    protected Integer passwordMinLength;
    protected Boolean passwordChangeDue;
    protected Integer thresholdDays;
    protected String updateUser;
    protected Integer version;
    protected List<String> processingOrg;
    @XmlAttribute
    protected String name;

    @Override
    public String getFullName() {
        return fullName;
    }

    @Override
    public void setFullName(String value) {
        fullName = value;
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public void setDescription(String value) {
        description = value;
    }

    @Override
    public Integer getLastPropertyNum() {
        return lastPropertyNum;
    }

    @Override
    public void setLastPropertyNum(Integer value) {
        lastPropertyNum = value;
    }

    @Override
    public Integer getLoginIddleDays() {
        return loginIddleDays;
    }

    @Override
    public void setLoginIddleDays(Integer value) {
        loginIddleDays = value;
    }

    @Override
    public Integer getMaxLoginAttempt() {
        return maxLoginAttempt;
    }

    @Override
    public void setMaxLoginAttempt(Integer value) {
        maxLoginAttempt = value;
    }

    @Override
    public Integer getMaxTrades() {
        return maxTrades;
    }

    @Override
    public void setMaxTrades(Integer value) {
        maxTrades = value;
    }

    @Override
    public Boolean isPasswordCheckDigit() {
        return passwordCheckDigit;
    }

    @Override
    public void setPasswordCheckDigit(Boolean value) {
        passwordCheckDigit = value;
    }

    @Override
    public Boolean isPasswordCheckSpecialChar() {
        return passwordCheckSpecialChar;
    }

    @Override
    public void setPasswordCheckSpecialChar(Boolean value) {
        passwordCheckSpecialChar = value;
    }

    @Override
    public Integer getPasswordMinLength() {
        return passwordMinLength;
    }

    @Override
    public void setPasswordMinLength(Integer value) {
        passwordMinLength = value;
    }

    @Override
    public Boolean isPasswordChangeDue() {
        return passwordChangeDue;
    }

    @Override
    public void setPasswordChangeDue(Boolean value) {
        passwordChangeDue = value;
    }

    @Override
    public Integer getThresholdDays() {
        return thresholdDays;
    }

    @Override
    public void setThresholdDays(Integer value) {
        thresholdDays = value;
    }

    @Override
    public String getUpdateUser() {
        return updateUser;
    }

    @Override
    public void setUpdateUser(String value) {
        updateUser = value;
    }

    @Override
    public Integer getVersion() {
        return version;
    }

    @Override
    public void setVersion(Integer value) {
        version = value;
    }

    @Override
    public List<String> getProcessingOrg() {
        if (processingOrg == null) {
            processingOrg = new ArrayList<>();
        }
        return processingOrg;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String value) {
        name = value;
    }

}

据我了解,下面的错误表明 JAXB 运行时无法猜测接口的正确实现,因为它不知道在许多可能的接口之间应该使用哪一个。

在独立项目中的 Eclipse 中运行时出现的错误如下:

javax.xml.bind.JAXBException: Provider com.sun.xml.bind.v2.ContextFactory could not be instantiated: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 4 counts of IllegalAnnotationExceptions
com.mycompany.user.UserList is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at com.mycompany.user.UserList
        at public com.mycompany.user.UserList com.mycompany.user.ObjectFactory.createUserList()
        at com.mycompany.user.ObjectFactory
com.mycompany.user.UserList does not have a no-arg default constructor.
    this problem is related to the following location:
        at com.mycompany.user.UserList
        at public com.mycompany.user.UserList com.mycompany.user.ObjectFactory.createUserList()
        at com.mycompany.user.ObjectFactory
com.mycompany.user.UserType is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at com.mycompany.user.UserType
        at public com.mycompany.user.UserType com.mycompany.user.ObjectFactory.createUserType()
        at com.mycompany.user.ObjectFactory
com.mycompany.user.UserType does not have a no-arg default constructor.
    this problem is related to the following location:
        at com.mycompany.user.UserType
        at public com.mycompany.user.UserType com.mycompany.user.ObjectFactory.createUserType()
        at com.mycompany.user.ObjectFactory

 - with linked exception:
[com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 4 counts of IllegalAnnotationExceptions
com.mycompany.user.UserList is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at com.mycompany.user.UserList
        at public com.mycompany.user.UserList com.mycompany.user.ObjectFactory.createUserList()
        at com.mycompany.user.ObjectFactory
com.mycompany.user.UserList does not have a no-arg default constructor.
    this problem is related to the following location:
        at com.mycompany.user.UserList
        at public com.mycompany.user.UserList com.mycompany.user.ObjectFactory.createUserList()
        at com.mycompany.user.ObjectFactory
com.mycompany.user.UserType is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at com.mycompany.user.UserType
        at public com.mycompany.user.UserType com.mycompany.user.ObjectFactory.createUserType()
        at com.mycompany.user.ObjectFactory
com.mycompany.user.UserType does not have a no-arg default constructor.
    this problem is related to the following location:
        at com.mycompany.user.UserType
        at public com.mycompany.user.UserType com.mycompany.user.ObjectFactory.createUserType()
        at com.mycompany.user.ObjectFactory
]
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:146)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:335)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:431)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:394)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:298)
    at com.mycompany.user.ImportUser.unmarshall(ImportUser.java:18)
    at com.mycompany.user.ImportUserTest.testUnmarshall(ImportUserTest.java:12)
    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:538)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 4 counts of IllegalAnnotationExceptions
com.mycompany.user.UserList is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at com.mycompany.user.UserList
        at public com.mycompany.user.UserList com.mycompany.user.ObjectFactory.createUserList()
        at com.mycompany.user.ObjectFactory
com.mycompany.user.UserList does not have a no-arg default constructor.
    this problem is related to the following location:
        at com.mycompany.user.UserList
        at public com.mycompany.user.UserList com.mycompany.user.ObjectFactory.createUserList()
        at com.mycompany.user.ObjectFactory
com.mycompany.user.UserType is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at com.mycompany.user.UserType
        at public com.mycompany.user.UserType com.mycompany.user.ObjectFactory.createUserType()
        at com.mycompany.user.ObjectFactory
com.mycompany.user.UserType does not have a no-arg default constructor.
    this problem is related to the following location:
        at com.mycompany.user.UserType
        at public com.mycompany.user.UserType com.mycompany.user.ObjectFactory.createUserType()
        at com.mycompany.user.ObjectFactory

    at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:102)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:472)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:302)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1140)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:154)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:121)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:202)
    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 javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:171)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:131)
    ... 29 more
java jaxb unmarshalling
1个回答
0
投票

我在

jaxb.properties
中有
src/main/java/com/mycompany/user
,必须移至
src/main/resources/com/mycompany/user
。 事实上,Gradle 会忽略
src/main/java
中的属性,并且不会将它们复制到构建文件夹中。

© www.soinside.com 2019 - 2024. All rights reserved.