【问题标题】:Class nor any of its super class is known to this context类或其任何超类在此上下文中是已知的
【发布时间】:2017-02-09 00:46:58
【问题描述】:

我试图了解我遇到的这个特殊问题。在这里使用 Spring OXM 来实现一个 Soap WS Consumer。

我只是附上相关信息来解释问题。

LoginWs配置,

@Configuration
public class LoginWsConfiguration {

    @Inject
    private OnboardingProperties onboardingProperties;

    @Bean
    Jaxb2Marshaller jaxb2Marshaller() {
        Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
        jaxb2Marshaller
            .setPackagesToScan("org.openiam.ws.login.api_3_2_6");
        try {
            jaxb2Marshaller.afterPropertiesSet();
        }
        catch (Exception ex) {
            throw new BeanCreationException(ex.getMessage(), ex);
        }
        return jaxb2Marshaller;
    }

    @Bean
    public WebServiceTemplate webServiceTemplate(Jaxb2Marshaller jaxb2Marshaller) {
        WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
        webServiceTemplate.setMarshaller(jaxb2Marshaller);
        webServiceTemplate.setUnmarshaller(jaxb2Marshaller);
        webServiceTemplate.setDefaultUri(onboardingProperties.getIAM().getEndpoint().getLogin());

        return webServiceTemplate;
    }

LoginClient 客户端实现为,

@Component
public class LoginClient {

    private static final Logger log = LoggerFactory.getLogger(IAMLoginClient.class);

    @Autowired
    private LoginMapper loginMapper;

    @Inject
    private OnboardingProperties onboardingProperties;

    private WebServiceTemplate webServiceTemplate;

    @Autowired
    public LoginClient(WebServiceTemplate webServiceTemplate) {
        this.webServiceTemplate = webServiceTemplate;
    }

    public LoginClient() {
    }

    public Optional getLoginByUserId(final String userId) {
        ObjectFactory factory = new ObjectFactory();
        GetLoginByUser req = factory.createGetLoginByUser();
        req.setUserId(userId);
        GetLoginByUserResponse resp = (GetLoginByUserResponse)webServiceTemplate.marshalSendAndReceive(req);
        if (resp != null && resp.getReturn() != null && resp.getReturn().getStatus() == org.openiam.ws.login.api_3_2_6.ResponseStatus.SUCCESS) {
            List<Login> foundLogins = resp.getReturn().getPrincipalLists();
            Login foundLogin = foundLogins.stream()
                .filter(login -> login.getManagedSysId().equals(Constants.IAM_DEFAULT_MANAGED_SYS_ID))
                .findFirst()
                .orElse(null);
            return Optional.ofNullable((foundLogin != null) ? this.loginMapper.mapIAMLogin(foundLogin) : null);
        }
        return Optional.empty();
    }

为了完整起见,GetLoginByUser,

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "getLoginByUser", propOrder = {
    "userId"
})
@XmlRootElement(name = "getLoginByUser")
public class GetLoginByUser {

    protected String userId;

    /**
     * Gets the value of the userId property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getUserId() {
        return userId;
    }

    /**
     * Sets the value of the userId property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setUserId(String value) {
        this.userId = value;
    }

}

GetLoginByUserResponse,

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "getLoginByUserResponse", propOrder = {
    "_return"
})
@XmlRootElement(name = "getLoginByUserResponse")
public class GetLoginByUserResponse {

    @XmlElement(name = "return")
    protected LoginListResponse _return;

    /**
     * Gets the value of the return property.
     * 
     * @return
     *     possible object is
     *     {@link LoginListResponse }
     *     
     */
    public LoginListResponse getReturn() {
        return _return;
    }

    /**
     * Sets the value of the return property.
     * 
     * @param value
     *     allowed object is
     *     {@link LoginListResponse }
     *     
     */
    public void setReturn(LoginListResponse value) {
        this._return = value;
    }

}

但是,当我尝试这样做时,

@Autowired
private UserClient iamUserClient;

@Autowired
private LoginClient iamLoginClient;

Optional<IAMUser> userFromIAM = iamUserClient.getUserByPrincipal(lowercaseLogin);
IAMUser userIAM = userFromIAM.
        orElseThrow(() -> new UsernameNotFoundException("User " + lowercaseLogin + " was not found in IAM"));
    if (userIAM.getStatus() != IAMUserStatus.ACTIVE || userIAM.getAccountStatus() != null) {
        throw new UserNotActivatedException("User " + lowercaseLogin + " is not active");
    }
Optional<IAMLogin> loginFromIAM = iamLoginClient.getLoginByUserId(userIAM.getId());

我得到了错误,

org.springframework.oxm.UncategorizedMappingException: Unknown JAXB exception; nested exception is javax.xml.bind.JAXBException: class org.openiam.ws.login.api_3_2_6.GetLoginByUser nor any of its super class is known to this context.
    at org.springframework.oxm.jaxb.Jaxb2Marshaller.convertJaxbException(Jaxb2Marshaller.java:915)
    at org.springframework.oxm.jaxb.Jaxb2Marshaller.marshal(Jaxb2Marshaller.java:684)
    at org.springframework.ws.support.MarshallingUtils.marshal(MarshallingUtils.java:81)
    at org.springframework.ws.client.core.WebServiceTemplate$2.doWithMessage(WebServiceTemplate.java:399)
    at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:590)
    at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555)
    at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:390)
    at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:383)
    at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:373)
    at com.orchestral.dsm.onboarding.iam.ws.login.LoginClient.getLoginByUserId(LoginClient.java:77)
    at com.orchestral.dsm.onboarding.security.IAMUserDetailsService.loadUserByUsername(IAMUserDetailsService.java:45)

据我所知,在编组 getUserByPrincipal (UserClient) 时它不会失败,但在 getLoginByUserId (LoginClient) 时失败。

【问题讨论】:

    标签: spring spring-boot wsdl wsdl2java spring-oxm


    【解决方案1】:

    这是因为两者都有,

    @Autowired
    private UserClient iamUserClient;
    
    @Autowired
    private LoginClient iamLoginClient;
    

    彼此冲突。拥有个人 jaxb2Marshaller 并将其传递给 WebServiceTemplate 解决了这个问题。

    所以 LoginWsConfiguration 更新为,

    @Configuration
    public class LoginWsConfiguration {
    
        @Bean
        Jaxb2Marshaller jaxb2LoginMarshaller() {
            Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
            jaxb2Marshaller.setPackagesToScan("org.openiam.ws.login.api_3_2_6");
            return jaxb2Marshaller;
        }
    
        @Bean
        public LoginClient loginClient(Jaxb2Marshaller jaxb2LoginMarshaller) {
            LoginClient client = new LoginClient();
            client.setMarshaller(jaxb2LoginMarshaller);
            client.setUnmarshaller(jaxb2LoginMarshaller);
            client.setDefaultUri("uri");
    
            return client;
        }
    }
    

    【讨论】:

    • 在我的测试中,UserClient和LoginClient的bean“Jaxb2Marshaller”的名称必须不同,否则会再次出现相同的错误消息,即使它们是在单独的类中定义的。
    【解决方案2】:

    这个配置在 Spring 4 上为我工作,现在在 Spring 5 中我看到 WebMvcConfigurerAdapter 已被弃用,但它仍然有效:

    @Configuration
    @EnableWebMvc
    @ComponentScan({})
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        public MappingJackson2HttpMessageConverter jacksonMessageConverter() {
            MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
            ObjectMapper mapper = new ObjectMapper(); 
            mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
    
            mapper.configure(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, false);
            mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    
            mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
    
            messageConverter.setObjectMapper(mapper);
            return messageConverter;
    
        }
    
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 
            converters.add(jacksonMessageConverter());
            super.configureMessageConverters(converters);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-16
      • 1970-01-01
      • 1970-01-01
      • 2021-05-27
      • 2012-12-13
      • 2013-09-13
      • 2012-03-01
      • 2014-07-03
      相关资源
      最近更新 更多