Wiki

Clone wiki

OCTitbit / samplec1

Передача изменений из 1С через JMS

В данной серии примеров мы рассмотрим работу с компонентом интеграции 1С и Apache Camel.
Сперва скажем несколько слов о самом компоненте и разберемся в терминах. Компонент состоит из "потребителя" (Consumer), "производителя" (Producer) и нескольких обработчиков (Processors).

  • Consumer - производит периодический просмотр EventLog 1С и, если имеются записи о новых событиях, выдает их в поток (в терминах Camel - route).
  • Producer - принимает на вход XML со стандартной для 1С структурой и записывает этот объект в базу 1С.
  • Processor - процессоры выполняют вспомогательные функции, например поиск объектов по UUID и т.д.
  • Route - это маршрут передвижения сообщений. От одного узла к другому. В начале маршрута всегда стоит Consumer, который принимает сообщения из вне (в нашем случае 1С).
    Внимание: для различных протоколов и систем Consumers и Producers работают по-разному. Например JMS Consumer читает сообщений из очереди. 1С Consumer читает сообщения из 1С.

    Маршруты и компоненты в Apache Camel могут конфигурироваться по-разному: Java DSL, XML DSL и прочие методы. В данном примере мы покажем как настроить интеграцию 1С и JMS без написания код - только конфигурирование с помощью XML. Конфигурационный XML по своей структуре является подмножеством XML для Spring Framework.

    Теперь от теории к практике.
    Начнем с конфигурирования базовых компонентов. На мужно настроить 1С и JMS компоненты.
	<bean id="ocx" class="com.ipc.oce.camel.OCXEComponent">
		<property name="host" value="192.168.10.142" />
		<property name="login" value="COMUser" />
		<property name="password" value="COMPassword" />
		<property name="dbpath" value="C:\Temp\1C" />
	</bean>
	
	<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
		<property name="connectionFactory">
			<bean class="org.apache.activemq.ActiveMQConnectionFactory">
				<property name="brokerURL" value="tcp://localhost:61616" />
			</bean>
		</property>
	</bean>


Объявляем два объекта(bean): ocx - компонент 1С, activemq - JMS компонент для JMS-провайдера Apache ActiveMQ. В OCX задаем настройки DCOM и путь до базы данных 1С. В ActiveMQ задаем url до брокера сообщений.

Теперь, настроим фильтрацию сообщений по типам и объектам. Предположим, что нам интересны только сообщений об изменениях документа "СчетНаОплатуПокупателю". Объявим списки фильтров.

	<bean id="dataChangesLevels" class="java.util.ArrayList">
		<constructor-arg>
			<list>
				<value>_$Data$_.New</value>
				<value>_$Data$_.Update</value>
				<value>_$Data$_.Delete</value>
			</list>
		</constructor-arg>
	</bean>
	<bean id="objectList" class="java.util.ArrayList">
		<constructor-arg>
			<list>
				<value>Document.СчетНаОплатуПокупателю</value>
			</list>
		</constructor-arg>
	</bean>


dataChangesLevels содержит список типов сообщений: _$Data$_.New, _$Data$_.Update и _$Data$_.Delete. objectList содержит список объектов отслеживания, например: Document.СчетНаОплатуПокупателю.

Теперь перейдем к самому маршруту:

	<camel:camelContext>
		<camel:route id="listenForChanges">
			<camel:from uri="ocx://EventsFrom1C?dbuser=OneUser&amp;dbpassword=OnePassword&amp;delay=5000&amp;eventTypes=#dataChangesLevels&amp;listenForObjects=#objectList" />
			<camel:split>
				<camel:xpath>/v8e:EventLog/v8e:Event</camel:xpath>
				<camel:idempotentConsumer eager="true" messageIdRepositoryRef="idempotentRepo">
				<camel:xpath resultType="java.lang.String">/v8e:Event/v8e:TransactionID</camel:xpath>
				<camel:filter>
					<camel:xpath>/v8e:Event/v8e:Level = 'Information'</camel:xpath>
					<camel:setProperty propertyName="LOOKUP_UUID">
						<camel:xpath resultType="java.lang.String">/v8e:Event/v8e:Data</camel:xpath>
					</camel:setProperty>
					<camel:setProperty propertyName="OBJECT_TYPE">
						<camel:xpath resultType="java.lang.String">/v8e:Event/v8e:MetadataName</camel:xpath>
					</camel:setProperty>
					<camel:process ref="lookupUUID"/>
					<camel:inOnly uri="activemq:queue:oct.activeobjects.out"/>
				</camel:filter>
				</camel:idempotentConsumer>
			</camel:split>
			
		</camel:route>
		<camel:route id="messageReader">
			<camel:from uri="activemq:queue:oct.activeobjects"/>
			<camel:process ref="view"/>
		</camel:route>
	</camel:camelContext>


Корневые элементы:
<camel:camelContext> - если не вдаватьяс в подробности, то это контейнер для маршрутов.
<camel:route id="listenForChanges"> - объявление маршрута для сообщений из 1С

<camel:from> - это Producer, от значения его uri зависит откуда и как он будет потреблять сообщения. В нашем случе мы его настраиваем на получение сообщений из 1С. uri компонента 1С состоит из префикса ocx, имени endpoint, например EventsFrom1C и списка параметров: логин\пароль пользователя 1С, интервал опроса, списки фильтров и т.д.

<camel:split> и <camel:xpath> разделяют полученный EventLog на отдельные сообщения в соответствии с XPath выражением /v8e:EventLog/v8e:Event.
<camel:filter> и <camel:xpath> отбирают только сообщения класса Information. XPath: /v8e:Event/v8e:Level = 'Information'

Далее из сообщения выделяется тип объекта метаданных и UUID и передается на вход процессору <camel:process ref="lookupUUID"/>, который ищет объект в базе 1С и сериализует его в XML и передает дальше компоненту activeMQ. Этот компонент пересылает входящее сообщеий с очередь JMS oct.activeobjects.out.

Маршрут для чтения сообщений из очереди queue:oct.activeobjects приведен ниже:

				<camel:route id="messageReader">
                        <camel:from uri="activemq:queue:oct.activeobjects"/>
                        <camel:process ref="view"/>
                </camel:route>




Дополнительно:

Updated