Java接口的JAXB IllegalAnnotationsException

时间:2015-09-02 10:21:23

标签: java xml jaxb

我正在尝试将用户记录缓存在XML文件中。为此,我编写了以下测试应用程序。

当我运行此操作时,我收到IllegalAnnotationsException。

以下是错误详情:

    Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
org.springframework.security.core.GrantedAuthority is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at org.springframework.security.core.GrantedAuthority
        at public java.util.Set User.getAuthorities()
        at User
        at public java.util.List UserXMLRepository$UserDataTable.users
        at UserXMLRepository$UserDataTable

    at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:445)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:124)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1123)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:147)
    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:497)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:462)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
    at UserXMLRepository.create(Test.java:64)
    at Test.main(Test.java:35)

测试申​​请:

    public class Test {
    public static void main(String[] args) throws Exception {
        UserXMLRepository.create();
    }
}

final class UserXMLRepository {

    public final static String rootDirectory = "E:/test";
    public final static String xmlFile = rootDirectory + "/userDataTable.xml";

    @XmlRootElement()
    public static final class UserDataTable {
        // XmLElementWrapper generates a wrapper element around XML representation
        @XmlElementWrapper(name = "userList")
        // XmlElement sets the name of the entities
        @XmlElement(name = "user")
        public List<User> users = new ArrayList<User>();
    }

    public static void create() throws JAXBException
    {
        File f = new File(rootDirectory);
        if(!f.exists())
            f.mkdirs();

        File xml = new File(xmlFile); 
        if(!xml.exists())
        {
            JAXBContext context;
            try {
                context = JAXBContext.newInstance(UserDataTable.class);
                Marshaller jaxbMarshaller  = context.createMarshaller();
                jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                jaxbMarshaller.marshal(new UserDataTable(), xml);

            } catch (JAXBException e) {
                throw e;
            }
        }
    }

    public static String getXmlfile() {
        return xmlFile;
    }

}

class User implements UserDetails {
    private static final long serialVersionUID = -4449202586601819593L;
    private String username;
    private String password;
    private Set<GrantedAuthority> authorities;
    private boolean accountNonExpired;
    private boolean accountNonLocked;
    private boolean credentialsNonExpired;
    private boolean enabled = true;
    public User() {
    }
    public User(String username, String password,
            Collection<? extends GrantedAuthority> authorities) {
        this(username, password, true, true, true, true, authorities);
    }
    public User(String username, String password, boolean enabled,
            boolean accountNonExpired, boolean credentialsNonExpired,
            boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
        this.username = username;
        this.password=password;
        this.accountNonExpired = accountNonExpired;
        this.credentialsNonExpired = credentialsNonExpired;
        this.accountNonLocked = accountNonLocked;
        this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities==null ? new ArrayList<GrantedAuthority>() : authorities));
    }

    private static SortedSet<GrantedAuthority> sortAuthorities(Collection<? extends GrantedAuthority> authorities) {
        Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
        // Ensure array iteration order is predictable (as per UserDetails.getAuthorities() contract and SEC-717)
        SortedSet<GrantedAuthority> sortedAuthorities =
            new TreeSet<GrantedAuthority>(new AuthorityComparator());

        for (GrantedAuthority grantedAuthority : authorities) {
            Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements");
            sortedAuthorities.add(grantedAuthority);
        }

        return sortedAuthorities;
    }

    private static class AuthorityComparator implements Comparator<GrantedAuthority>, Serializable {
        private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
        public int compare(GrantedAuthority g1, GrantedAuthority g2) {
            if (g2.getAuthority() == null) {
                return -1;
            }
            if (g1.getAuthority() == null) {
                return 1;
            }
            return g1.getAuthority().compareTo(g2.getAuthority());
        }
    }

    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public Set<GrantedAuthority> getAuthorities() {
        return authorities;
    }
    public void setAuthorities(Set<GrantedAuthority> authorities) {
        this.authorities = authorities;
    }
    public boolean isAccountNonExpired() {
        return accountNonExpired;
    }
    public void setAccountNonExpired(boolean accountNonExpired) {
        this.accountNonExpired = accountNonExpired;
    }
    public boolean isAccountNonLocked() {
        return accountNonLocked;
    }
    public void setAccountNonLocked(boolean accountNonLocked) {
        this.accountNonLocked = accountNonLocked;
    }
    public boolean isCredentialsNonExpired() {
        return credentialsNonExpired;
    }
    public void setCredentialsNonExpired(boolean credentialsNonExpired) {
        this.credentialsNonExpired = credentialsNonExpired;
    }
    public boolean isEnabled() {
        return enabled;
    }
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
}

错误说User类中的方法getAuthorities()返回一个接口,而JAXB无法处理接口。

那么这个问题的解决方法是什么?

提前致谢。

1 个答案:

答案 0 :(得分:0)

您是否尝试使用@XmlTransient在User类中注释getAuthorities()?

我实现了几乎相同的实现生成JSON的Rest服务:

   @Override
   @JsonIgnore  //Tell Jackson to ignore this metod, you can use @XMLTransient
   public Collection<? extends GrantedAuthority> getAuthorities() {
       Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
       if (getRole() != null) {
        for (Right right : getRole().getRights()) {
          GrantedAuthority authority = new GrantedAuthority(right.getName());
          authorities.add(authority);
        }
     }
     return authorities;
   }