es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Obteniendo ForbiddenClassException en Axon/SpringBoot

Estoy tratando de implementar el marco de trabajo Axon con Spring Boot.

Aquí está la versión de los archivos JAR:
1. Spring Boot 2.6.1
2. Java 17
3. Axon 4.5.6

La estructura de mi proyecto es la siguiente:
– user-command
– user-query
– user-core (un archivo JAR común que contiene eventos)

Recibo la siguiente excepción al intentar acceder al evento UserRegisteredEvent desde la aplicación de consulta:

com.thoughtworks.xstream.security.ForbiddenClassException: com.tesla.user.core.events.UserRegisteredEvent
    at com.thoughtworks.xstream.security.NoTypePermission.allows(NoTypePermission.java:26) ~[xstream-1.4.18.jar:1.4.18]

¿Dónde estoy cometiendo un error?

Nota:

He intentado reducir la versión de Java a 16 y también la de Spring Boot a 2.4.*.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    La excepción que estás enfrentando está relacionada con la serialización de la clase UserRegisteredEvent. Parece que la biblioteca xstream que estás utilizando no está permitida para serializar/deserializar la clase UserRegisteredEvent de forma predeterminada.

    Una solución para abordar este problema es agregar la clase UserRegisteredEvent a la lista blanca de xstream.
    Para hacerlo, crea una clase que extienda la clase XStream y añade la clase UserRegisteredEvent a los tipos permitidos. Aquí tienes un ejemplo:

    import com.tesla.user.core.events.*;
    import com.thoughtworks.xstream.XStream;
    
    public class CustomXStream extends XStream {
    
        public CustomXStream() {
            super();
            allowTypeHierarchy(UserRegisteredEvent.class);
        }
    }
    

    Luego, modifica tu aplicación de consulta para usar esta clase CustomXStream en lugar de la clase XStream por defecto. Aquí tienes un ejemplo:

    import com.tesla.user.core.events.*;
    
    public class QueryApplication {
        public static void main(String[] args) {
            CustomXStream xStream = new CustomXStream();
            // usa xStream para deserializar UserRegisteredEvent
            // resto de tu código...
        }
    }
    

    Alternativamente, también puedes cambiar a otra biblioteca de serialización que admita la serialización de la clase UserRegisteredEvent. Por ejemplo, puedes utilizar la biblioteca Jackson añadiendo la siguiente dependencia a tu archivo pom.xml:

    <dependency>
        <groupid>com.fasterxml.jackson.core</groupid>
        <artifactid>jackson-databind</artifactid>
        <version>2.12.5</version>
    </dependency>
    

    Luego, modifica tu clase CustomXStream para utilizar la biblioteca Jackson:

    import com.tesla.user.core.events.*;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.dataformat.xml.XmlMapper;
    import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
    
    public class CustomXStream extends XStream {
    
        public CustomXStream() {
            super(new XmlMapper());
            setMarshallingStrategy(new JacksonXmlMarshallingStrategy());
            ((XmlMapper) marshaller()).configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true);
    
            allowTypes(new Class[]{UserRegisteredEvent.class});
        }
    
        private static class JacksonXmlMarshallingStrategy extends AbstractMarshallingStrategy {
    
            private ObjectMapper objectMapper = new ObjectMapper();
    
            @Override
            protected String aliasForSystemAttribute(String systemAttributeName) {
                return null;
            }
    
            @Override
            protected String aliasForAttribute(String attribute) {
                return null;
            }
    
            @Override
            protected void configureXStream(XStream xstream) {
            }
    
            @Override
            public void marshal(Object o, XMLEventWriter xmlEventWriter) {
                try {
                    String xml = objectMapper.writeValueAsString(o);
                    xmlEventWriter.add(XMLInputFactory.newInstance().createXMLEventReader(new StringReader(xml)));
                } catch (XMLStreamException | JsonProcessingException e) {
                    throw new RuntimeException(e);
                }
            }
    
            @Override
            public Object unmarshal(XMLEventReader xmlEventReader) {
                try {
                    return objectMapper.readValue(XMLInputFactory.newInstance().createXMLStreamReader(xmlEventReader), Object.class);
                } catch (XMLStreamException | JsonProcessingException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    

    Luego, modifica tu aplicación de consulta para usar esta clase CustomXStream en lugar de la clase XStream por defecto. Aquí tienes un ejemplo:

    import com.tesla.user.core.events.*;
    
    public class QueryApplication {
        public static void main(String[] args) {
            CustomXStream xStream = new CustomXStream();
            // use xStream to deserialize the UserRegisteredEvent
            // rest of your code...
        }
    }
    

    Espero que esto te ayude a resolver el problema.

Comments are closed.