这是一个单元测试,当我在 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
我在
jaxb.properties
中有 src/main/java/com/mycompany/user
,必须移至 src/main/resources/com/mycompany/user
。
事实上,Gradle 会忽略 src/main/java
中的属性,并且不会将它们复制到构建文件夹中。