ClientSymmetricEngine 3.12.7 - 无法编译 IAcknowledgeEventListener Java 扩展点

问题描述

在使 SymmetricDS java 扩展点工作时费了一番功夫。

这是我试过的:

1.创建了这个类:


package com.gourmet.listener;

import org.jumpmind.symmetric.ISymmetricEngine;
import org.jumpmind.symmetric.ext.ISymmetricEngineAware;
import org.jumpmind.symmetric.model.BatchAck;
import org.jumpmind.symmetric.transport.IAckNowledgeEventListener;

public class AckNowledgeListener implements IAckNowledgeEventListener,ISymmetricEngineAware {
    ISymmetricEngine _engine;


    @Override
    public void onAckNowledgeEvent(BatchAck batchInfo) {
        if (!batchInfo.isOk()) {
            System.out.println("bachInfo is not OK " + batchInfo);
            return;
        }
        System.out.println("received event!!!!!!! {}" + batchInfo);
    }

    @Override
    public void setSymmetricEngine(ISymmetricEngine engine) {
        _engine = engine;

    }
}

2.将 `Manifest.txt 放置在与 AckNowledgeListener.java 相同的包位置

Class-Path: symmetric-core-3.12.7.jar symmetric-util-3.12.7.jar

3.用AckNowledgeListener生成jar文件放在WEB-INF/lib

cd /gourmet3/mobile-webpage/src/main/java

javac -cp ".:/gourmet3/mobile-webpage/target/gourmet/WEB-INF/lib/symmetric-util-3.12.7.jar:/gourmet3/mobile-webpage/target/gourmet/WEB-INF/lib/symmetric-core-3.12.7.jar" com/gourmet/listener/AckNowledgeListener.java

jar cfm com/gourmet/listener/AckNowledgeListener.jar com/gourmet/listener/Manifest.txt com/gourmet/listener/*.class

mv com/gourmet/listener/AckNowledgeListener.jar /gourmet3/mobile-webpage/src/main/webapp/WEB-INF/lib

rm com/gourmet/listener/AckNowledgeListener.*

结果如下:

enter image description here

MANIFEST.MF:

Manifest-Version: 1.0
Class-Path: symmetric-core-3.12.7.jar symmetric-util-3.12.7.jar
Created-By: 1.8.0_272 (Azul Systems,Inc.)

正如 SymmetricDS 3.2 documentation 所述,我创建了 conf/symmetric-extensions.xml 以便 spring 找到 bean。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="ackNowledgeListener" class="com.gourmet.listener.AckNowledgeListener"/>
</beans>

在服务器和客户端数据库中创建了 sym_extension 条目 sql

insert into sym_extension (extension_id,extension_type,interface_name,node_group_id,enabled,extension_order,extension_text,create_time,last_update_by,last_update_time)
values ('ackNowledge batch','java','org.jumpmind.symmetric.transport.IAckNowledgeEventListener','sucursal',1,'
import org.jumpmind.symmetric.ISymmetricEngine;
import org.jumpmind.symmetric.ext.ISymmetricEngineAware;
import org.jumpmind.symmetric.model.BatchAck;
import org.jumpmind.symmetric.transport.IAckNowledgeEventListener;

public class AckNowledgeListener implements IAckNowledgeEventListener,ISymmetricEngineAware {
    ISymmetricEngine _engine;


    @Override
    public void onAckNowledgeEvent(BatchAck batchInfo) {
        if (!batchInfo.isOk()) {
            System.out.println("bachInfo is not OK " + batchInfo);
            return;
        }
        System.out.println("received event!!!!!!! {}" + batchInfo);
    }

    @Override
    public void setSymmetricEngine(ISymmetricEngine engine) {
        _engine = engine;

    }
}
',current_timestamp,'some user',current_timestamp);

当我尝试运行 Sym 客户端时,我总是遇到异常。

20 Mar 2021 20:17:10 ERROR [org.jumpmind.symmetric.service.impl.ExtensionService] - <Error while compiling Java extension ackNowledge batch>
org.jumpmind.util.SimpleClassCompilerException: Compilation of 'AckNowledgeListener' Failed.
AckNowledgeListener at line 2,column 30: package org.jumpmind.symmetric does not exist
AckNowledgeListener at line 3,column 34: package org.jumpmind.symmetric.ext does not exist
AckNowledgeListener at line 4,column 36: package org.jumpmind.symmetric.model does not exist
AckNowledgeListener at line 5,column 40: package org.jumpmind.symmetric.transport does not exist
AckNowledgeListener at line 7,column 46: cannot find symbol
  symbol: class IAckNowledgeEventListener
AckNowledgeListener at line 7,column 73: cannot find symbol
  symbol: class ISymmetricEngineAware
AckNowledgeListener at line 8,column 5: cannot find symbol
  symbol:   class ISymmetricEngine
  location: class SimpleClassCompiler0
AckNowledgeListener at line 12,column 36: cannot find symbol
  symbol:   class BatchAck
  location: class SimpleClassCompiler0
AckNowledgeListener at line 21,column 36: cannot find symbol
  symbol:   class ISymmetricEngine
  location: class SimpleClassCompiler0
AckNowledgeListener at line 11,column 5: method does not override or implement a method from a supertype
AckNowledgeListener at line 20,column 5: method does not override or implement a method from a supertype

    at org.jumpmind.util.SimpleClassCompiler.getCompiledClass(SimpleClassCompiler.java:119)
    at org.jumpmind.symmetric.service.impl.ExtensionService.registerExtension(ExtensionService.java:110)
    at org.jumpmind.symmetric.service.impl.ExtensionService.refresh(ExtensionService.java:101)
    at org.jumpmind.symmetric.service.impl.ClientExtensionService.refresh(ClientExtensionService.java:46)
    at org.jumpmind.symmetric.AbstractSymmetricEngine.init(AbstractSymmetricEngine.java:348)
    at org.jumpmind.symmetric.ClientSymmetricEngine.init(ClientSymmetricEngine.java:205)
    at org.jumpmind.symmetric.ClientSymmetricEngine.<init>(ClientSymmetricEngine.java:148)
    at org.jumpmind.symmetric.ClientSymmetricEngine.<init>(ClientSymmetricEngine.java:152)
    at com.gourmet.symmetricds.SymdsStarter.postconstruct(SymdsStarter.java:54)
    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:498)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:346)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:299)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:132)
    at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapablebeanfactory.java:394)
    at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.initializeBean(AbstractAutowireCapablebeanfactory.java:1448)
    at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.doCreateBean(AbstractAutowireCapablebeanfactory.java:519)
    at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.createBean(AbstractAutowireCapablebeanfactory.java:456)
    at org.springframework.beans.factory.support.Abstractbeanfactory$1.getobject(Abstractbeanfactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.Abstractbeanfactory.doGetBean(Abstractbeanfactory.java:291)
    at org.springframework.beans.factory.support.Abstractbeanfactory.getBean(Abstractbeanfactory.java:193)
    at org.springframework.beans.factory.support.DefaultListablebeanfactory.preInstantiateSingletons(DefaultListablebeanfactory.java:609)
    at org.springframework.context.support.AbstractApplicationContext.finishbeanfactoryInitialization(AbstractApplicationContext.java:918)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:469)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:383)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)
    at org.springframework.web.context.ContextLoaderListener.contextinitialized(ContextLoaderListener.java:111)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4705)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5171)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:743)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:719)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:705)
    at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1663)
    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:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:286)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at org.apache.catalina.mbeans.Mbeanfactory.createStandardContext(Mbeanfactory.java:482)
    at org.apache.catalina.mbeans.Mbeanfactory.createStandardContext(Mbeanfactory.java:431)
    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:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:286)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at com.sun.jmx.remote.security.MBeanServerAccessController.invoke(MBeanServerAccessController.java:468)
    at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
    at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
    at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1408)
    at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
    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:498)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

注意事项:

  1. 我试过在 sql 脚本中使用 & 不使用 package com.gourmet.listener; 路径。
  2. 我从 com.gourmet.listener 包中删除了 java 和编译的 .class 文件
  3. symmetric-core-3.12.7.jarsymmetric-util-3.12.7.jarAckNowledgeListener.jar 存在于 WEB-INF/lib。

所以,不确定我错过了什么?

HAAALP!

编辑

这太奇怪了,我注释掉了插入 sym_extension 并删除了所有表行(来自服务器和客户端数据库)的脚本,.jar 文件留在了 WEB-INF\lib 中,而我所在的包中的 java 文件编译它,突然它起作用了,我什至能够调试。当 sym_extension 表中没有行时,为什么 symmetricDS 甚至调用它?

enter image description here

解决方法

扩展基本功能的类不应放在自定义包中。删除该行:

package com.gourmet.listener;

然后添加具有以下内容的文件 conf/symmetric-extensions.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--

    Licensed to JumpMind Inc under one or more contributor
    license agreements.  See the NOTICE file distributed
    with this work for additional information regarding
    copyright ownership.  JumpMind Inc licenses this file
    to you under the GNU General Public License,version 3.0 (GPLv3)
    (the "License"); you may not use this file except in compliance
    with the License.

    You should have received a copy of the GNU General Public License,version 3.0 (GPLv3) along with this library; if not,see
    <http://www.gnu.org/licenses/>.

    Unless required by applicable law or agreed to in writing,software distributed under the License is distributed on an
    "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND,either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.

-->
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
       default-lazy-init="true">

    <bean id="acknowledgeListener" class="AcknowledgeListener" />
</beans>
,

如果您使用 sym_extension 表作为您的扩展代码,那么就没有什么可做的了。优点是您的扩展成为配置的一部分。您将 SymmetricDS 部署到 Tomcat,看起来它的类加载器层次结构正在阻止编译。如果您使用独立的 SymmetricDS 服务器,它会工作。

如果您将代码编译为 JAR,则可以将 Spring XML 文件放入名为 symmetric-extensions.xml 的 JAR 中,该 JAR 位于“conf”子目录中,该 JAR 会将您的扩展注册为 Spring bean。或者您可以编辑文件 conf/symmetric-extensions.xml,它是 SymmetricDS 安装的一部分。我更喜欢将文件放在 JAR 中,这样它是独立的。