Инициировать, пропагандировать, проверить, отправить, и маршал сообщение весной


Цель кода

Целью настоящего Кодекса является:

  1. Инициировать распространение сообщений в другие системы
  2. Проверить, что данное сообщение придерживается своей схемы xsd, а затем Маршалл
  3. Отправить его по маршруту на верблюдах, когда она проверена и упорядочено

Этот код находится на узле, который является самой низкой в иерархии. Он предназначен для распространения различных форматов сообщений вверх на другие узлы. Чтобы убедиться, что каждый узел способен обрабатывать формат входящих данных, xsd-файл используется для облегчения мобилизации/распаковки и проверки данных. В файлы xsd используются для создания объектов POJO в проектах построения шаг, и эти POJO-объекты находятся в общем модуле, что каждый узел имеет доступ. При получении сообщения по маршруту верблюдов, затем получающая система немаршаллом сообщение и проверит его содержание.

Фон

Я хочу, чтобы реализовать единый формат данных и легко обмениваться данными между заинтересованными сторонами, просто давая им доступ к формату данных (объекты POJO). Я хочу убедиться, что данные, отправленные придерживается схемы, ею же порожденных. Это участие в капитальном ремонте системы, в которой были огромные XML-сообщения, отправленные туда и обратно, где был использован только часть данных. Удаление любой части этих сообщений был весьма неустойчивым, поскольку оно было почти невозможно сказать, если и где данные были использованы.

Код

Хотелось бы какой-то вклад в решение я работаю недавно. Я знаю, что это нарушает СРП в PropagationEventListenerно это работа, и кроме того, я бы любого входа, в основном по ООП и твердые принципы.

Проект построен весной.

Цепочка начинается здесь, где я выдавать событие, которое призвано распространяться вне существующей системы:

private void publishEvent(InventoryUpdate inventoryUpdate) {
    context.getPublisher().publishEvent(
            new PropagationEvent(new InventoryUpdateWrapper(inventoryUpdate), getInventoryUpdateEndpoint()));
}

В InventoryUpdateWrapper что я посылаю на своем пути:

public class InventoryUpdateWrapper extends AbstractXsdValidationObject {

    public InventoryUpdateWrapper(Object sourceObject) {
        super(sourceObject);
    }

    @Override
    public String getXsdSchemaPath() {
        return "xsd/InventoryUpdate.xsd";
    }
}

В PropagationEvent класс:

public class PropagationEvent extends ApplicationEvent {

    private static final long serialVersionUID = 1851493071586088471L;

    private String targetCamelEndpoint;

    public PropagationEvent(AbstractXsdValidationObject source, final String targetCamelEndpoint) {
        super(source);
        this.targetCamelEndpoint = targetCamelEndpoint;
    }

    public String getTargetCamelEndpoint() {
        return targetCamelEndpoint;
    }
}

В AbstractXsdValidationObject класс:

public abstract class AbstractXsdValidationObject implements XsdValidationObject {

    Object sourceObject;

    public AbstractXsdValidationObject(Object sourceObject) {
        this.sourceObject = sourceObject;
    }

    @Override
    public abstract String getXsdSchemaPath();

    @Override
    public Object getSourceObject() {
        return sourceObject;
    }

    public Schema getXsdSchema() throws SAXException {
        File xsdSchemaFile = getXsdSchemaAsFile();
        return SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(xsdSchemaFile);
    }

    private File getXsdSchemaAsFile() {
        return new File(getPathFromResource());
    }

    private String getPathFromResource() {
        return getClass().getClassLoader().getResource(getXsdSchemaPath()).getFile();
    }

}

И, наконец, PropagationEventListener класс, где это все сшиты вместе:

public class PropagationEventListener implements ApplicationListener<PropagationEvent> {

    @Autowired
    private JAXBContext jaxbContext;

    private ProducerTemplate producer;

    public PropagationEventListener(final ProducerTemplate producer) {
        this.producer = producer;
    }

    @Override
    public void onApplicationEvent(PropagationEvent event) {
        String messageBody = validateAndMarshall(event);
        producer.sendBody(event.getTargetCamelEndpoint(), messageBody);
    }

    private String validateAndMarshall(PropagationEvent event) {
        AbstractXsdValidationObject source = (AbstractXsdValidationObject) event.getSource();
        Schema schema = getSchema(source);

        Marshaller jaxbMarshaller = createMarshaller(schema);

        return marshallToString(source.getSourceObject(), jaxbMarshaller);
    }

    private Schema getSchema(AbstractXsdValidationObject source) {
        try {
            return source.getXsdSchema();
        } catch (SAXException e) {
            throw new XmlException("Failed to create and XSD schema instance from " + source.getXsdSchemaPath(), e);
        } 
    }

    private Marshaller createMarshaller(Schema schema) {
        try {
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            jaxbMarshaller.setSchema(schema);
            return jaxbMarshaller;
        } catch (JAXBException e) {
            throw new XmlException("Failed to create marshaller", e);
        }
    }

    private String marshallToString(Object event, Marshaller jaxbMarshaller) {
        try {
            StringWriter stringWriter = new StringWriter();
            jaxbMarshaller.marshal(event, stringWriter);
            return stringWriter.toString();
        } catch (JAXBException e) {
            throw new XmlException("Failed to marshal XML to String", e);
        }
    }
}

Некоторые свои мысли

С помощью абстрактного класса, чтобы обернуть объекты, которые создаются из схемы xsd, я хочу сделать это трудно, чтобы отправить все, что не подкреплено схемы для других систем, а также придерживаться принципа инверсии зависимостей. Я хочу придерживаться открытости/закрытости, сделав PropagationEventListener не зная никаких подробностей. Он просто знает, что он будет способен обрабатывать и проверять входящих на объект, а затем отправить его на своем пути по заданному маршруту. Я хочу легко сможете добавить любой другой формат по мере роста системы данных.

При возникновении ошибок, я решил создать свое собственное исключение, которое распространяется RuntimeException. Мой вот думает, что нет никакого способа, чтобы смягчить ошибки валидации / маршалинга, если он получил это далеко. Я просто хочу, чтобы прервать последовательность и ошибка в логах. Я разрешаю только один конструктор на xmlexception в всегда вам причину.

Я планирую сделать кроссировка/обратный/проверки в своем классе, что utilizies одноэлементный JAXBContext, и тогда я думаю, что я сделал.

Я интерпретировал принципы?



128
2
задан 20 февраля 2018 в 08:02 Источник Поделиться
Комментарии