Having a hell of a time making SymmetricDS java extension points work.
This is what I've tried:
1. created this class:
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. Placed `Manifest.txt in the same package location as AcknowledgeListener.java
Class-Path: symmetric-core-3.12.7.jar symmetric-util-3.12.7.jar
3. Generated jar file with AcknowledgeListener and placed it in 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.*
This is the result:
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.)
As SymmetricDS 3.2 documentation states, I created conf/symmetric-extensions.xml so spring finds the 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>
Created the sym_extension entry SQL in the server and client databases
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, 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);
And when I try to run the Sym Client, i always get an exception.
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)
Notes:
- I've tried with & without package com.gourmet.listener; path in the SQL script.
- I removed the java and compiled .class files from com.gourmet.listener package.
- symmetric-core-3.12.7.jar, symmetric-util-3.12.7.jar and AcknowledgeListener.jar exist into WEB-INF/lib.
So, not sure what am I missing?
HAAALP!
EDIT
This is so weird, I commented out the script which inserts into sym_extension and deleted all table rows (from server and client DBs), .jar file was left in WEB-INF\lib and the java file in the package where I compiled it, and suddenly it worked and I'm even able to debug. Why is symmetricDS even calling it when there's no rows in the sym_extension table??

