From adcefa1bbab0521138353c4ce9ee9d68b4eafa8b Mon Sep 17 00:00:00 2001 From: Brian Rosenberger Date: Tue, 26 Sep 2023 08:43:16 +0000 Subject: [PATCH] First version 2.0.0 release. git-svn-id: https://brutex.net/svn/xservices/trunk@203 e7e49efb-446e-492e-b9ec-fcafc1997a86 --- build.gradle | 4 - .../types/alfevent/ALFEventBase_1.xsd | 354 +++++++++++++ .../types/alfevent/ALFEventManagerDocLit.xsd | 202 +++++++ .../types/alfevent/ALFEventResponseType.java | 49 +- .../types/alfevent/ALFEventType.java | 2 +- .../ALFEventWithReplyResponseType.java | 49 +- .../types/alfevent/ALFSecurityType.java | 255 +++++++++ .../types/alfevent/BaseExtensionType.java | 4 +- .../types/alfevent/CredentialsType.java | 38 +- .../types/alfevent/CustomExtensionType.java | 5 +- .../types/alfevent/DetailExtensionType.java | 5 +- .../xservices/types/alfevent/EmBaseType.java | 30 +- .../types/alfevent/EmExtensionType.java | 4 +- .../types/alfevent/EventBaseType.java | 4 +- .../types/alfevent/ObjectFactory.java | 24 +- .../brutex/xservices/util/EventEmitter.java | 22 +- .../xservices/util/EventLogCleanerJob.java | 83 +++ .../util/EventmanagerConfiguration.java | 8 +- .../MiscServiceServletContextListener.java | 75 ++- .../net/brutex/xservices/util/SimpleSoap.java | 15 +- .../net/brutex/xservices/ws/MiscService.java | 5 +- .../xservices/ws/impl/MiscServiceImpl.java | 501 ++++++++++-------- src/main/resources/ddl/BRTX_schema.ddl | 21 +- .../WEB-INF/data/getEventManagerStatus.sql | 10 + .../WEB-INF}/eventmanager.properties | 17 +- src/main/webapp/WEB-INF/web.xml | 15 +- 26 files changed, 1458 insertions(+), 343 deletions(-) create mode 100644 src/main/java/net/brutex/xservices/types/alfevent/ALFEventBase_1.xsd create mode 100644 src/main/java/net/brutex/xservices/types/alfevent/ALFEventManagerDocLit.xsd create mode 100644 src/main/java/net/brutex/xservices/types/alfevent/ALFSecurityType.java create mode 100644 src/main/java/net/brutex/xservices/util/EventLogCleanerJob.java create mode 100644 src/main/webapp/WEB-INF/data/getEventManagerStatus.sql rename src/main/{resources => webapp/WEB-INF}/eventmanager.properties (53%) diff --git a/build.gradle b/build.gradle index 69f0cac..c5474fa 100644 --- a/build.gradle +++ b/build.gradle @@ -91,10 +91,6 @@ dependencies { implementation "org.quartz-scheduler:quartz:2.3.2" - //implementation "org.apache.logging.log4j:log4j-core:2.20.0" - //implementation "org.apache.logging.log4j:log4j-web:2.20.0" - //implementation "org.apache.logging.log4j:log4j-1.2-api:2.20.0" - //implementation "org.apache.logging.log4j:log4j-slf4j18-impl:2.18.0" implementation "org.slf4j:slf4j-api:2.0.7" runtimeOnly "org.slf4j:slf4j-simple:2.0.7" diff --git a/src/main/java/net/brutex/xservices/types/alfevent/ALFEventBase_1.xsd b/src/main/java/net/brutex/xservices/types/alfevent/ALFEventBase_1.xsd new file mode 100644 index 0000000..bea3030 --- /dev/null +++ b/src/main/java/net/brutex/xservices/types/alfevent/ALFEventBase_1.xsd @@ -0,0 +1,354 @@ + + + + Copyright Notice The material in this document is Copyright + (c) Serena Software, Inc. and others, 2005, 2006, 2007 Terms and + Conditions: The Eclipse Foundation makes available all + content in this document ("Content"). Unless otherwise + indicated below, the Content is provided to you under the + terms and conditions of the Eclipse Public License Version + 1.0 ("EPL"). A copy of the EPL is available at + http://www.eclipse.org/legal/epl-v10.html. For purposes of + the EPL, "Program" will mean the Content. If you did not + receive this Content directly from the Eclipse Foundation, + the Content is being redistributed by another party + ("Redistributor") and different terms and conditions may + apply to your use of any object code in the Content. Check + the Redistributor's license that was provided with the + Content. If you did not receive any such license, contact + the Redistributor. Unless otherwise indicated below, the + terms and conditions of the EPL still apply to the Content. + + + + + + EventBaseType is a container for that portion of an ALF + Event that is generally set by the Tool that raises the + event. + + + + + + + + + + + + + + + + + + + EventControlType is a container for that portion of an + ALF Event that is generally set by the ALF EventManager. + In some cases, ALF compliant tools may set some fields, + in particular when the event is a result of an ALF + service call to that tool from a ServiceFlow. + + + + + + + + + + + + + + + + + + + + + + A id that uniquely identifies the Event instance at the source. + + + + + + + + + + A UUID that uniquely identifies the Event instance. + + + + + + + + + + A UUID that uniquely identifies the ServiceFlow + instance. + + + + + + + + + + The date and timestamp when the EventManager received + the Event. This element may be left empty by the event + emitter, in which case, the Event Manager will supply a + value. + + + + + + + + A string indicating the type of event. EventType + designates the verb. That is what action happened to the + Objects that triggered the event. + + + + + + + + An ObjectId identifies the entity or relationship that + changed within a tool. The identifier must be unique for + a particular instance of the source tool. The format of + this element will not be standardized by ALF. The + primary purpose is to allow subsequent ServiceFlows to + uniquely identify (and perhaps access) the object that + triggered the event. + + + + + + + + The type of entity involved. Note that the word entity + is taken in its broadest sense, referring to whatever + artifact a tool was operating on. For example, for a + data modeling tool, an E-R relationship is a type of + entity (i.e., and ObjectType) to ALF. + + + + + + + + A Source element is a container type that describes the + source of the event. ProductCallbackURI is optional for + tools that don't provide a listener to accept the + callback from a tool or serviceflow at a later time. + + + + + + + + + + + + + A descriptive name for the tool (i.e., program) that + emitted the Event. Note that this is a datatype for a + Product element. + + + + + + + + The web service endpoint for tools that support + callbacks from ServiceFlows for additional information. + The element content is optional for transient tools that + may not be running at a later time, and so cannot accept + a callback. Constantly running (server) tools that + support callbacks should supply a URI. + + + + + + + + A unique string identifying the instance of the tool. + This is useful when there may be multiple instances of a + product working within an instance of ALF. + + + + + + + + The release version of the product, such as 5.06 + + + + + + + + + + + + + + + + + + + + + + + A structure to hold security + authentication-relevant data. If present the + data within may be encrypted. + + + + + + + + + + + + The name of the ALF application to which this event + belongs. Depending on the emitting tool, events may or + may not be associated with an ALF application. If the + emitting tool has the information available then it can + provide the ALF ApplicationName as an additional + information to distinguish the event. + + + + + + + + The name of the event match within the ALF Application + that matches this event. This fields is set by the Event + Manager when it dispatches the event. + + + + + + + + The name of the service flow withing the event match + that matches this event. This field is set by the Event + Manager when it dispatches the event. + + + + + + + + The name of the environment in which this event is being + raised. This element will be set by the ALF Event + manager from its installation configuration. + + + + + + + + + + + + + Place holder type for future extensions of + BaseExtensionType + + + + + + + + + + + Place holder type for future extensions of EmBaseType + + + + + + + + + + + Place holder type for vocabulary based Event payload + "details" + + + + + + + + + + + Place holder type for custom Event payload "extensions" + ##other namespace is recommended but ##any is specified allowing more primitive sources + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/net/brutex/xservices/types/alfevent/ALFEventManagerDocLit.xsd b/src/main/java/net/brutex/xservices/types/alfevent/ALFEventManagerDocLit.xsd new file mode 100644 index 0000000..d2c6b23 --- /dev/null +++ b/src/main/java/net/brutex/xservices/types/alfevent/ALFEventManagerDocLit.xsd @@ -0,0 +1,202 @@ + + + + WARNING: PRELIMINARY VERSION SUBJECT TO CHANGE + + Copyright Notice The material in this document is Copyright (c) + Serena Software, Inc. and others, 2005, 2006, 2007, 2008 Terms and + Conditions: The Eclipse Foundation makes available all content + in this document ("Content"). Unless otherwise indicated below, + the Content is provided to you under the terms and conditions of + the Eclipse Public License Version 1.0 ("EPL"). A copy of the + EPL is available at http://www.eclipse.org/legal/epl-v10.html. + For purposes of the EPL, "Program" will mean the Content. If you + did not receive this Content directly from the Eclipse + Foundation, the Content is being redistributed by another party + ("Redistributor") and different terms and conditions may apply + to your use of any object code in the Content. Check the + Redistributor's license that was provided with the Content. If + you did not receive any such license, contact the Redistributor. + Unless otherwise indicated below, the terms and conditions of + the EPL still apply to the Content. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/net/brutex/xservices/types/alfevent/ALFEventResponseType.java b/src/main/java/net/brutex/xservices/types/alfevent/ALFEventResponseType.java index 0e67c41..efe0094 100644 --- a/src/main/java/net/brutex/xservices/types/alfevent/ALFEventResponseType.java +++ b/src/main/java/net/brutex/xservices/types/alfevent/ALFEventResponseType.java @@ -1,10 +1,13 @@ package net.brutex.xservices.types.alfevent; +import java.util.ArrayList; +import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAnyElement; import javax.xml.bind.annotation.XmlType; +import org.w3c.dom.Element; /** @@ -17,7 +20,7 @@ import javax.xml.bind.annotation.XmlType; * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> - * <any minOccurs="0"/> + * <any processContents='lax' maxOccurs="unbounded" minOccurs="0"/> * </sequence> * </restriction> * </complexContent> @@ -33,30 +36,36 @@ import javax.xml.bind.annotation.XmlType; public class ALFEventResponseType { @XmlAnyElement(lax = true) - protected Object any; + protected List any; /** - * Ruft den Wert der any-Eigenschaft ab. + * Gets the value of the any property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the any property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAny().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Element } + * {@link Object } * - * @return - * possible object is - * {@link Object } - * - */ - public Object getAny() { - return any; - } - - /** - * Legt den Wert der any-Eigenschaft fest. * - * @param value - * allowed object is - * {@link Object } - * */ - public void setAny(Object value) { - this.any = value; + public List getAny() { + if (any == null) { + any = new ArrayList(); + } + return this.any; } } diff --git a/src/main/java/net/brutex/xservices/types/alfevent/ALFEventType.java b/src/main/java/net/brutex/xservices/types/alfevent/ALFEventType.java index 776d275..f888840 100644 --- a/src/main/java/net/brutex/xservices/types/alfevent/ALFEventType.java +++ b/src/main/java/net/brutex/xservices/types/alfevent/ALFEventType.java @@ -145,8 +145,8 @@ public class ALFEventType { * *

* Objects of the following type(s) are allowed in the list - * {@link Object } * {@link Element } + * {@link Object } * * */ diff --git a/src/main/java/net/brutex/xservices/types/alfevent/ALFEventWithReplyResponseType.java b/src/main/java/net/brutex/xservices/types/alfevent/ALFEventWithReplyResponseType.java index 0548f17..20b8b77 100644 --- a/src/main/java/net/brutex/xservices/types/alfevent/ALFEventWithReplyResponseType.java +++ b/src/main/java/net/brutex/xservices/types/alfevent/ALFEventWithReplyResponseType.java @@ -1,10 +1,13 @@ package net.brutex.xservices.types.alfevent; +import java.util.ArrayList; +import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAnyElement; import javax.xml.bind.annotation.XmlType; +import org.w3c.dom.Element; /** @@ -17,7 +20,7 @@ import javax.xml.bind.annotation.XmlType; * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> - * <any minOccurs="0"/> + * <any processContents='lax' maxOccurs="unbounded" minOccurs="0"/> * </sequence> * </restriction> * </complexContent> @@ -33,30 +36,36 @@ import javax.xml.bind.annotation.XmlType; public class ALFEventWithReplyResponseType { @XmlAnyElement(lax = true) - protected Object any; + protected List any; /** - * Ruft den Wert der any-Eigenschaft ab. + * Gets the value of the any property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the any property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAny().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Element } + * {@link Object } * - * @return - * possible object is - * {@link Object } - * - */ - public Object getAny() { - return any; - } - - /** - * Legt den Wert der any-Eigenschaft fest. * - * @param value - * allowed object is - * {@link Object } - * */ - public void setAny(Object value) { - this.any = value; + public List getAny() { + if (any == null) { + any = new ArrayList(); + } + return this.any; } } diff --git a/src/main/java/net/brutex/xservices/types/alfevent/ALFSecurityType.java b/src/main/java/net/brutex/xservices/types/alfevent/ALFSecurityType.java new file mode 100644 index 0000000..7636b4a --- /dev/null +++ b/src/main/java/net/brutex/xservices/types/alfevent/ALFSecurityType.java @@ -0,0 +1,255 @@ + +package net.brutex.xservices.types.alfevent; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAnyAttribute; +import javax.xml.bind.annotation.XmlAnyElement; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.namespace.QName; +import org.w3c.dom.Element; + + +/** + *

Java-Klasse für ALFSecurityType complex type. + * + *

Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist. + * + *

+ * <complexType name="ALFSecurityType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="UsernameToken">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <sequence>
+ *                   <element name="Username" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="Password" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <any processContents='lax' maxOccurs="unbounded" minOccurs="0"/>
+ *                 </sequence>
+ *                 <anyAttribute/>
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *         <any processContents='lax' maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ALFSecurityType", namespace = "http://www.eclipse.org/alf/schema/EventBase/1", propOrder = { + "usernameToken", + "any" +}) +public class ALFSecurityType { + + @XmlElement(name = "UsernameToken", namespace = "http://www.eclipse.org/alf/schema/EventBase/1", required = true) + protected ALFSecurityType.UsernameToken usernameToken; + @XmlAnyElement(lax = true) + protected List any; + + /** + * Ruft den Wert der usernameToken-Eigenschaft ab. + * + * @return + * possible object is + * {@link ALFSecurityType.UsernameToken } + * + */ + public ALFSecurityType.UsernameToken getUsernameToken() { + return usernameToken; + } + + /** + * Legt den Wert der usernameToken-Eigenschaft fest. + * + * @param value + * allowed object is + * {@link ALFSecurityType.UsernameToken } + * + */ + public void setUsernameToken(ALFSecurityType.UsernameToken value) { + this.usernameToken = value; + } + + /** + * Gets the value of the any property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the any property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAny().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Element } + * {@link Object } + * + * + */ + public List getAny() { + if (any == null) { + any = new ArrayList(); + } + return this.any; + } + + + /** + *

Java-Klasse für anonymous complex type. + * + *

Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist. + * + *

+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <sequence>
+     *         <element name="Username" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <element name="Password" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <any processContents='lax' maxOccurs="unbounded" minOccurs="0"/>
+     *       </sequence>
+     *       <anyAttribute/>
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
+     * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "username", + "password", + "any" + }) + public static class UsernameToken { + + @XmlElement(name = "Username", namespace = "http://www.eclipse.org/alf/schema/EventBase/1", required = true) + protected String username; + @XmlElement(name = "Password", namespace = "http://www.eclipse.org/alf/schema/EventBase/1", required = true) + protected String password; + @XmlAnyElement(lax = true) + protected List any; + @XmlAnyAttribute + private Map otherAttributes = new HashMap(); + + /** + * Ruft den Wert der username-Eigenschaft ab. + * + * @return + * possible object is + * {@link String } + * + */ + public String getUsername() { + return username; + } + + /** + * Legt den Wert der username-Eigenschaft fest. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setUsername(String value) { + this.username = value; + } + + /** + * Ruft den Wert der password-Eigenschaft ab. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPassword() { + return password; + } + + /** + * Legt den Wert der password-Eigenschaft fest. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPassword(String value) { + this.password = value; + } + + /** + * Gets the value of the any property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the any property. + * + *

+ * For example, to add a new item, do as follows: + *

+         *    getAny().add(newItem);
+         * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Element } + * {@link Object } + * + * + */ + public List getAny() { + if (any == null) { + any = new ArrayList(); + } + return this.any; + } + + /** + * Gets a map that contains attributes that aren't bound to any typed property on this class. + * + *

+ * the map is keyed by the name of the attribute and + * the value is the string value of the attribute. + * + * the map returned by this method is live, and you can add new attribute + * by updating the map directly. Because of this design, there's no setter. + * + * + * @return + * always non-null + */ + public Map getOtherAttributes() { + return otherAttributes; + } + + } + +} diff --git a/src/main/java/net/brutex/xservices/types/alfevent/BaseExtensionType.java b/src/main/java/net/brutex/xservices/types/alfevent/BaseExtensionType.java index 37c3945..696bc0f 100644 --- a/src/main/java/net/brutex/xservices/types/alfevent/BaseExtensionType.java +++ b/src/main/java/net/brutex/xservices/types/alfevent/BaseExtensionType.java @@ -11,6 +11,7 @@ import javax.xml.bind.annotation.XmlAnyAttribute; import javax.xml.bind.annotation.XmlAnyElement; import javax.xml.bind.annotation.XmlType; import javax.xml.namespace.QName; +import org.w3c.dom.Element; /** @@ -28,7 +29,7 @@ import javax.xml.namespace.QName; * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> - * <any namespace='targetnamespace' maxOccurs="unbounded"/> + * <any processContents='lax' namespace='http://www.eclipse.org/alf/schema/EventBase/1' maxOccurs="unbounded"/> * </sequence> * <anyAttribute/> * </restriction> @@ -67,6 +68,7 @@ public class BaseExtensionType { * *

* Objects of the following type(s) are allowed in the list + * {@link Element } * {@link Object } * * diff --git a/src/main/java/net/brutex/xservices/types/alfevent/CredentialsType.java b/src/main/java/net/brutex/xservices/types/alfevent/CredentialsType.java index d9fac1b..3c8026a 100644 --- a/src/main/java/net/brutex/xservices/types/alfevent/CredentialsType.java +++ b/src/main/java/net/brutex/xservices/types/alfevent/CredentialsType.java @@ -9,6 +9,7 @@ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAnyAttribute; import javax.xml.bind.annotation.XmlAnyElement; +import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; import javax.xml.namespace.QName; import org.w3c.dom.Element; @@ -16,8 +17,9 @@ import org.w3c.dom.Element; /** * - * A structure to hold security authentication-relevant data. - * If present the data within may be encrypted. + * A structure to hold security + * authentication-relevant data. If present the + * data within may be encrypted. * * *

Java-Klasse für CredentialsType complex type. @@ -29,7 +31,8 @@ import org.w3c.dom.Element; * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> - * <any processContents='lax' maxOccurs="unbounded" minOccurs="0"/> + * <element name="ALFSecurity" type="{http://www.eclipse.org/alf/schema/EventBase/1}ALFSecurityType" minOccurs="0"/> + * <any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/> * </sequence> * <anyAttribute/> * </restriction> @@ -41,15 +44,42 @@ import org.w3c.dom.Element; */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "CredentialsType", namespace = "http://www.eclipse.org/alf/schema/EventBase/1", propOrder = { + "alfSecurity", "any" }) public class CredentialsType { + @XmlElement(name = "ALFSecurity", namespace = "http://www.eclipse.org/alf/schema/EventBase/1") + protected ALFSecurityType alfSecurity; @XmlAnyElement(lax = true) protected List any; @XmlAnyAttribute private Map otherAttributes = new HashMap(); + /** + * Ruft den Wert der alfSecurity-Eigenschaft ab. + * + * @return + * possible object is + * {@link ALFSecurityType } + * + */ + public ALFSecurityType getALFSecurity() { + return alfSecurity; + } + + /** + * Legt den Wert der alfSecurity-Eigenschaft fest. + * + * @param value + * allowed object is + * {@link ALFSecurityType } + * + */ + public void setALFSecurity(ALFSecurityType value) { + this.alfSecurity = value; + } + /** * Gets the value of the any property. * @@ -68,8 +98,8 @@ public class CredentialsType { * *

* Objects of the following type(s) are allowed in the list - * {@link Object } * {@link Element } + * {@link Object } * * */ diff --git a/src/main/java/net/brutex/xservices/types/alfevent/CustomExtensionType.java b/src/main/java/net/brutex/xservices/types/alfevent/CustomExtensionType.java index fa8e332..7956f87 100644 --- a/src/main/java/net/brutex/xservices/types/alfevent/CustomExtensionType.java +++ b/src/main/java/net/brutex/xservices/types/alfevent/CustomExtensionType.java @@ -17,6 +17,7 @@ import org.w3c.dom.Element; /** * * Place holder type for custom Event payload "extensions" + * ##other namespace is recommended but ##any is specified allowing more primitive sources * * *

Java-Klasse für CustomExtensionType complex type. @@ -28,7 +29,7 @@ import org.w3c.dom.Element; * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> - * <any processContents='lax' namespace='##other' maxOccurs="unbounded"/> + * <any processContents='lax' maxOccurs="unbounded"/> * </sequence> * <anyAttribute/> * </restriction> @@ -67,8 +68,8 @@ public class CustomExtensionType { * *

* Objects of the following type(s) are allowed in the list - * {@link Object } * {@link Element } + * {@link Object } * * */ diff --git a/src/main/java/net/brutex/xservices/types/alfevent/DetailExtensionType.java b/src/main/java/net/brutex/xservices/types/alfevent/DetailExtensionType.java index ebf8e04..451b327 100644 --- a/src/main/java/net/brutex/xservices/types/alfevent/DetailExtensionType.java +++ b/src/main/java/net/brutex/xservices/types/alfevent/DetailExtensionType.java @@ -16,7 +16,8 @@ import org.w3c.dom.Element; /** * - * Place holder type for vocabulary based Event payload "details" + * Place holder type for vocabulary based Event payload + * "details" * * *

Java-Klasse für DetailExtensionType complex type. @@ -67,8 +68,8 @@ public class DetailExtensionType { * *

* Objects of the following type(s) are allowed in the list - * {@link Object } * {@link Element } + * {@link Object } * * */ diff --git a/src/main/java/net/brutex/xservices/types/alfevent/EmBaseType.java b/src/main/java/net/brutex/xservices/types/alfevent/EmBaseType.java index 19d09dc..1a32942 100644 --- a/src/main/java/net/brutex/xservices/types/alfevent/EmBaseType.java +++ b/src/main/java/net/brutex/xservices/types/alfevent/EmBaseType.java @@ -31,7 +31,7 @@ import javax.xml.namespace.QName; * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> - * <element name="EmEventId" type="{http://www.w3.org/2001/XMLSchema}string"/> + * <element name="EmEventId" type="{http://www.eclipse.org/alf/schema/EventBase/1}EventIdType"/> * <element name="EmTimestamp" type="{http://www.eclipse.org/alf/schema/EventBase/1}TimestampType"/> * <element name="PrecedingEmEventId" type="{http://www.eclipse.org/alf/schema/EventBase/1}EventIdType"/> * <element name="ApplicationName" type="{http://www.eclipse.org/alf/schema/EventBase/1}ApplicationNameType"/> @@ -41,6 +41,7 @@ import javax.xml.namespace.QName; * <element name="Callback" type="{http://www.w3.org/2001/XMLSchema}boolean"/> * <element name="Environment" type="{http://www.eclipse.org/alf/schema/EventBase/1}EnvironmentType"/> * <element name="EmUser" type="{http://www.eclipse.org/alf/schema/EventBase/1}CredentialsType"/> + * <element name="AttemptCount" type="{http://www.w3.org/2001/XMLSchema}int" minOccurs="0"/> * <element name="EmExtension" type="{http://www.eclipse.org/alf/schema/EventBase/1}EmExtensionType" minOccurs="0"/> * </sequence> * <anyAttribute/> @@ -63,6 +64,7 @@ import javax.xml.namespace.QName; "callback", "environment", "emUser", + "attemptCount", "emExtension" }) public class EmBaseType { @@ -88,6 +90,8 @@ public class EmBaseType { protected String environment; @XmlElement(name = "EmUser", namespace = "http://www.eclipse.org/alf/schema/EventBase/1", required = true) protected CredentialsType emUser; + @XmlElement(name = "AttemptCount", namespace = "http://www.eclipse.org/alf/schema/EventBase/1") + protected Integer attemptCount; @XmlElement(name = "EmExtension", namespace = "http://www.eclipse.org/alf/schema/EventBase/1") protected EmExtensionType emExtension; @XmlAnyAttribute @@ -325,6 +329,30 @@ public class EmBaseType { this.emUser = value; } + /** + * Ruft den Wert der attemptCount-Eigenschaft ab. + * + * @return + * possible object is + * {@link Integer } + * + */ + public Integer getAttemptCount() { + return attemptCount; + } + + /** + * Legt den Wert der attemptCount-Eigenschaft fest. + * + * @param value + * allowed object is + * {@link Integer } + * + */ + public void setAttemptCount(Integer value) { + this.attemptCount = value; + } + /** * Ruft den Wert der emExtension-Eigenschaft ab. * diff --git a/src/main/java/net/brutex/xservices/types/alfevent/EmExtensionType.java b/src/main/java/net/brutex/xservices/types/alfevent/EmExtensionType.java index 49db1d2..d821630 100644 --- a/src/main/java/net/brutex/xservices/types/alfevent/EmExtensionType.java +++ b/src/main/java/net/brutex/xservices/types/alfevent/EmExtensionType.java @@ -11,6 +11,7 @@ import javax.xml.bind.annotation.XmlAnyAttribute; import javax.xml.bind.annotation.XmlAnyElement; import javax.xml.bind.annotation.XmlType; import javax.xml.namespace.QName; +import org.w3c.dom.Element; /** @@ -27,7 +28,7 @@ import javax.xml.namespace.QName; * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> - * <any namespace='targetnamespace' maxOccurs="unbounded"/> + * <any processContents='lax' namespace='http://www.eclipse.org/alf/schema/EventBase/1' maxOccurs="unbounded"/> * </sequence> * <anyAttribute/> * </restriction> @@ -66,6 +67,7 @@ public class EmExtensionType { * *

* Objects of the following type(s) are allowed in the list + * {@link Element } * {@link Object } * * diff --git a/src/main/java/net/brutex/xservices/types/alfevent/EventBaseType.java b/src/main/java/net/brutex/xservices/types/alfevent/EventBaseType.java index 217db38..8f77e4a 100644 --- a/src/main/java/net/brutex/xservices/types/alfevent/EventBaseType.java +++ b/src/main/java/net/brutex/xservices/types/alfevent/EventBaseType.java @@ -29,7 +29,7 @@ import javax.xml.namespace.QName; * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> - * <element name="EventId" type="{http://www.eclipse.org/alf/schema/EventBase/1}EventIdType"/> + * <element name="EventId" type="{http://www.eclipse.org/alf/schema/EventBase/1}SourceEventIdType"/> * <element name="Timestamp" type="{http://www.eclipse.org/alf/schema/EventBase/1}TimestampType"/> * <element name="EventType" type="{http://www.eclipse.org/alf/schema/EventBase/1}EventTypeType"/> * <element name="ObjectType" type="{http://www.eclipse.org/alf/schema/EventBase/1}ObjectTypeType"/> @@ -63,7 +63,7 @@ public class EventBaseType { @XmlElement(name = "EventId", namespace = "http://www.eclipse.org/alf/schema/EventBase/1", required = true) protected String eventId; - @XmlElement(name = "Timestamp", namespace = "http://www.eclipse.org/alf/schema/EventBase/1", required = true) + @XmlElement(name = "Timestamp", namespace = "http://www.eclipse.org/alf/schema/EventBase/1", required = true, nillable = true) @XmlSchemaType(name = "dateTime") protected XMLGregorianCalendar timestamp; @XmlElement(name = "EventType", namespace = "http://www.eclipse.org/alf/schema/EventBase/1", required = true) diff --git a/src/main/java/net/brutex/xservices/types/alfevent/ObjectFactory.java b/src/main/java/net/brutex/xservices/types/alfevent/ObjectFactory.java index 3d902d6..aa0330d 100644 --- a/src/main/java/net/brutex/xservices/types/alfevent/ObjectFactory.java +++ b/src/main/java/net/brutex/xservices/types/alfevent/ObjectFactory.java @@ -24,7 +24,7 @@ import javax.xml.namespace.QName; @XmlRegistry public class ObjectFactory { - private final static QName _EventNotice_QNAME = new QName("http://www.eclipse.org/alf/schema/EventBase/1", "EventNotice"); + private final static QName _ALFEventNoticeDoc_QNAME = new QName("http://www.eclipse.org/alf/schema/EventBase/1", "ALFEventNoticeDoc"); /** * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: net.brutex.xservices.types.alfevent @@ -33,6 +33,14 @@ public class ObjectFactory { public ObjectFactory() { } + /** + * Create an instance of {@link ALFSecurityType } + * + */ + public ALFSecurityType createALFSecurityType() { + return new ALFSecurityType(); + } + /** * Create an instance of {@link ALFEventType } * @@ -121,13 +129,21 @@ public class ObjectFactory { return new EmBaseType(); } + /** + * Create an instance of {@link ALFSecurityType.UsernameToken } + * + */ + public ALFSecurityType.UsernameToken createALFSecurityTypeUsernameToken() { + return new ALFSecurityType.UsernameToken(); + } + /** * Create an instance of {@link JAXBElement }{@code <}{@link ALFEventType }{@code >}} * */ - @XmlElementDecl(namespace = "http://www.eclipse.org/alf/schema/EventBase/1", name = "EventNotice") - public JAXBElement createEventNotice(ALFEventType value) { - return new JAXBElement(_EventNotice_QNAME, ALFEventType.class, null, value); + @XmlElementDecl(namespace = "http://www.eclipse.org/alf/schema/EventBase/1", name = "ALFEventNoticeDoc") + public JAXBElement createALFEventNoticeDoc(ALFEventType value) { + return new JAXBElement(_ALFEventNoticeDoc_QNAME, ALFEventType.class, null, value); } } diff --git a/src/main/java/net/brutex/xservices/util/EventEmitter.java b/src/main/java/net/brutex/xservices/util/EventEmitter.java index 9b37b71..48ee4c3 100644 --- a/src/main/java/net/brutex/xservices/util/EventEmitter.java +++ b/src/main/java/net/brutex/xservices/util/EventEmitter.java @@ -51,10 +51,11 @@ public class EventEmitter implements Job, InterruptableJob { * Move event table data to snapshot */ - Connection con = null; - Connection fcon = null; - try { - con = pool.getConnection(); + + try( Connection con = pool.getConnection(); + Connection fcon = fpool.getConnection(); + ) { + con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); con.setAutoCommit(false); Statement stmt = con.createStatement(); @@ -65,7 +66,7 @@ public class EventEmitter implements Job, InterruptableJob { con.commit(); //all events moved from tbl_events to tbl_events_snap at this point - fcon = fpool.getConnection(); + PreparedStatement errorPrepSql = fcon.prepareStatement(moveErrorSQL); PreparedStatement del = con.prepareStatement(deleteSQL); @@ -83,7 +84,8 @@ public class EventEmitter implements Job, InterruptableJob { long event_ts = rs.getLong(6); boolean bretry = false; - SimpleSoap ss = new SimpleSoap( url, id, IOUtils.toString(c.getCharacterStream())); + //SimpleSoap ss = new SimpleSoap( url, id, IOUtils.toString(c.getAsciiStream()c.getCharacterStream())); + SimpleSoap ss = new SimpleSoap(url, id, c.getSubString(1L, (int) c.length())); int retry = 0; Reader response = null; String rsp = ""; @@ -152,14 +154,6 @@ public class EventEmitter implements Job, InterruptableJob { } catch (IOException e) { log.error("Exception in SQL execution: {}", e.getMessage()); throw new RuntimeException(e); - } finally { - try { - if(fcon!=null) fcon.close(); - if(con!=null) con.close(); - } catch (SQLException e) { - log.error("Error closing the database connections: {}", e.getMessage()); - throw new RuntimeException(e); - } } } diff --git a/src/main/java/net/brutex/xservices/util/EventLogCleanerJob.java b/src/main/java/net/brutex/xservices/util/EventLogCleanerJob.java new file mode 100644 index 0000000..2326539 --- /dev/null +++ b/src/main/java/net/brutex/xservices/util/EventLogCleanerJob.java @@ -0,0 +1,83 @@ +package net.brutex.xservices.util; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; +import org.h2.jdbcx.JdbcConnectionPool; +import org.quartz.*; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.sql.*; +import java.time.Instant; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; + +@Slf4j +@DisallowConcurrentExecution +public class EventLogCleanerJob implements Job, InterruptableJob { + + private final AtomicBoolean isInterrupted = new AtomicBoolean(false); + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + final Instant d = Instant.now(); + final long ts = d.toEpochMilli(); + + log.info("EventLogCleaner is executing now."); + final EventmanagerConfiguration conf = (EventmanagerConfiguration) context.getMergedJobDataMap() + .get(EventmanagerConfiguration.KEY); + + final JdbcConnectionPool fpool = (JdbcConnectionPool) context.getMergedJobDataMap().get("fdbConnection"); + final JdbcConnectionPool mpool = (JdbcConnectionPool) context.getMergedJobDataMap().get("mdbConnection"); + + final String moveSQL = "INSERT INTO brutex.tbl_events_all DIRECT SELECT * FROM MEM_ALL_EVENTS " + + "where btx_timestamp < " + (ts-5000) + " "; + final String deleteTable = "DELETE FROM MEM_ALL_EVENTS where btx_timestamp < " + (ts-5000); + final String deleteMemTable = "DELETE FROM brutex.tbl_events_all where btx_timestamp < " + (ts-5000); + + + /** + * Move event table data to all events log + */ + + + try (Connection fcon = fpool.getConnection(); + Connection mcon = mpool.getConnection()){ + fcon.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); + fcon.setAutoCommit(false); + Statement stmt = fcon.createStatement(); + stmt.execute(moveSQL); + int count = stmt.getUpdateCount(); + fcon.commit(); + Statement mstm = mcon.createStatement(); + + + mstm.execute(deleteMemTable); + int count2 = mstm.getUpdateCount(); + mcon.commit(); + + log.info("EventLogCleaner moved '{}/ deleted {}' events into the persistence space.", count, count2); + + } catch (SQLException e) { + log.error("Exception in SQL execution: {}", e.getMessage()); + throw new JobExecutionException(e); + } + } + + + /** + *

+ * Called by the {@link Scheduler} when a user + * interrupts the Job. + *

+ * + * @throws UnableToInterruptJobException if there is an exception while interrupting the job. + */ + @Override + public synchronized void interrupt() throws UnableToInterruptJobException { + isInterrupted.set(true); + log.warn("EventLogCleaner received and interrupt."); + Thread.currentThread().interrupt(); + } +} diff --git a/src/main/java/net/brutex/xservices/util/EventmanagerConfiguration.java b/src/main/java/net/brutex/xservices/util/EventmanagerConfiguration.java index efde8a9..cdf0d5b 100644 --- a/src/main/java/net/brutex/xservices/util/EventmanagerConfiguration.java +++ b/src/main/java/net/brutex/xservices/util/EventmanagerConfiguration.java @@ -8,6 +8,8 @@ import org.apache.commons.configuration2.FileBasedConfiguration; import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder; import org.apache.commons.configuration2.builder.PropertiesBuilderParametersImpl; +import org.apache.commons.configuration2.event.ConfigurationEvent; +import org.apache.commons.configuration2.event.EventListener; import org.apache.commons.configuration2.ex.ConfigurationException; import javax.servlet.ServletContext; @@ -39,13 +41,15 @@ public class EventmanagerConfiguration { private int interval; private String jdbc_memdb; private String jdbc_filedb; + private boolean isEmitterActive = true; + private int cleaner_interval; public synchronized EventmanagerConfiguration refreshConfig() { log.trace("Reading EventmanagerConfiguration from file eventmanager.properties."); FileBasedConfigurationBuilder builder = new FileBasedConfigurationBuilder(PropertiesConfiguration.class) - .configure(new PropertiesBuilderParametersImpl().setFileName("eventmanager.properties")); + .configure(new PropertiesBuilderParametersImpl().setFileName("../eventmanager.properties")); try { Configuration config = builder.getConfiguration(); @@ -55,6 +59,8 @@ public class EventmanagerConfiguration { this.interval = config.getInt("interval", 10); this.jdbc_memdb = config.getString("memdb", "jdbc:h2:mem:lockdb;DB_CLOSE_DELAY=-1;"); this.jdbc_filedb = config.getString("fdb", "jdbc:h2:mem:lockdb;DB_CLOSE_DELAY=-1;"); + this.isEmitterActive = config.getBoolean("emitter_active", true); + this.cleaner_interval = config.getInt("cleaner_interval", 5); } catch (ConfigurationException e) { diff --git a/src/main/java/net/brutex/xservices/util/MiscServiceServletContextListener.java b/src/main/java/net/brutex/xservices/util/MiscServiceServletContextListener.java index c06cd0e..77a1eef 100644 --- a/src/main/java/net/brutex/xservices/util/MiscServiceServletContextListener.java +++ b/src/main/java/net/brutex/xservices/util/MiscServiceServletContextListener.java @@ -15,6 +15,8 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; import java.util.concurrent.atomic.AtomicLong; import static org.quartz.TriggerBuilder.newTrigger; @@ -48,12 +50,12 @@ public class MiscServiceServletContextListener implements ServletContextListener */ private static JdbcConnectionPool getDbPool(String dbConnectString) { JdbcConnectionPool p = JdbcConnectionPool.create(dbConnectString, "", ""); - p.setMaxConnections(16); - p.setLoginTimeout(5); - try { - Connection c = p.getConnection(); + p.setMaxConnections(256); + p.setLoginTimeout(20); + try (Connection c = p.getConnection();){ Statement s = c.createStatement(); s.execute(dbinit); + c.commit(); log.trace("Running SQL against database '{}': '{}'", dbConnectString, dbinit); c.close(); log.debug("Successfully created schema for database 'Brutex' at '{}'.", dbConnectString); @@ -72,12 +74,18 @@ public class MiscServiceServletContextListener implements ServletContextListener log.debug("Active jobs to be terminated: {}", scheduler.getCurrentlyExecutingJobs()); JobKey key = JobKey.jobKey("ALFEmitter"); + JobKey cleanerkey = JobKey.jobKey("EventLogCleaner"); synchronized (scheduler) { if (!scheduler.isShutdown() && scheduler.checkExists(key) ) { scheduler.interrupt(key); scheduler.deleteJob(key); log.info("Gracefully stopped the ALFEventEmitter job."); } + if (!scheduler.isShutdown() && scheduler.checkExists(cleanerkey) ) { + scheduler.interrupt(cleanerkey); + scheduler.deleteJob(cleanerkey); + log.info("Gracefully stopped the ALFEventEmitter job."); + } if (!scheduler.isShutdown()) { scheduler.shutdown(true); } @@ -98,12 +106,19 @@ public class MiscServiceServletContextListener implements ServletContextListener Connection con = fdbpool.getConnection(); Statement s = con.createStatement(); - final String insert = "INSERT INTO brutex.tbl_events SELECT * from LINK UNION SELECT " + "btx_event_type, btx_id, btx_obj_type, btx_obj_id, btx_timestamp, btx_event from LINK2;"; + final String insert = "INSERT INTO brutex.tbl_events SELECT * from MEM_INBOUND UNION SELECT " + "btx_event_type, btx_id, btx_obj_type, btx_obj_id, btx_timestamp, btx_event from MEM_OUTBOUND;"; s.execute(insert); int count = s.getUpdateCount(); - log.info("Persisted {} rows in file-based database.", count); + log.info("Persisted {} active event rows in file-based database.", count); + + final String save_all = "INSERT INTO brutex.tbl_events_all SELECT * from MEM_ALL_EVENTS;"; + s.execute(save_all); + count = s.getUpdateCount(); + log.info("Persisted {} event rows from all_events log in file-based database", count); + log.info("Shutting down in-memory database. Closing file-based database. Please wait ..."); s.execute("SHUTDOWN;"); + con.close(); log.info("Shutting down databases complete."); } catch (SQLException e) { @@ -141,9 +156,8 @@ public class MiscServiceServletContextListener implements ServletContextListener //Load events from file based database into in-memory database try { log.info("Start recovery of previously unsend alf events. Trying to load them into in-memory database."); - final String link = "CREATE LINKED TABLE IF NOT EXISTS LINK('org.h2.Driver', '"+configuration.getJdbc_memdb()+"', '', '', 'brutex.tbl_events'); " + - "CREATE LINKED TABLE IF NOT EXISTS LINK2('org.h2.Driver', '"+configuration.getJdbc_memdb()+"', '', '', 'brutex.tbl_events_snap');"; - final String recoverSQL = "INSERT INTO LINK DIRECT SELECT * FROM brutex.tbl_events;"; + final String link = getLinkSQL(); + final String recoverSQL = "INSERT INTO MEM_INBOUND DIRECT SELECT * FROM brutex.tbl_events;"; final String truncate = "TRUNCATE TABLE brutex.tbl_events;"; int count = 0; Connection con = fdbpool.getConnection(); @@ -163,17 +177,33 @@ public class MiscServiceServletContextListener implements ServletContextListener throw new RuntimeException(e); } //Start initial run of the emitter - startEmitterImmediate(egres, (Scheduler) context.getAttribute("scheduler")); + if(configuration.isEmitterActive()) { + startEmitterImmediate(egres, (Scheduler) context.getAttribute("scheduler")); + } + + //Start mem db log cleaner + if(configuration.getCleaner_interval()>0) { + startEventLogCleaner((Scheduler) context.getAttribute("scheduler")); + } } - private synchronized void startEmitterImmediate(AtomicLong egres_counter, Scheduler scheduler) { + private String getLinkSQL() { + final String dbDriverClass = "org.h2.Driver"; + final String link = "CREATE LINKED TABLE IF NOT EXISTS MEM_INBOUND('"+dbDriverClass+"', '"+configuration.getJdbc_memdb()+"', '', '', 'brutex.tbl_events'); " + + "CREATE LINKED TABLE IF NOT EXISTS MEM_OUTBOUND('"+dbDriverClass+"', '"+configuration.getJdbc_memdb()+"', '', '', 'brutex.tbl_events_snap'); " + + "CREATE LINKED TABLE IF NOT EXISTS MEM_ALL_EVENTS('"+dbDriverClass+"', '"+configuration.getJdbc_memdb()+"', '', '', 'brutex.tbl_events_all') AUTOCOMMIT OFF; " + + ""; + return link; + } + + private synchronized void startEmitterImmediate(AtomicLong egres, Scheduler scheduler) { try { if (!scheduler.checkExists(JobKey.jobKey("ALFEmitter"))) { JobDetail job2 = JobBuilder.newJob(EventEmitter.class).withIdentity("ALFEmitter").build(); job2.getJobDataMap().put("mdbConnection", mempool); job2.getJobDataMap().put("fdbConnection", fdbpool); job2.getJobDataMap().put("run_key", Instant.now().toEpochMilli()); - job2.getJobDataMap().put("egres_counter", egres_counter); + job2.getJobDataMap().put("egres_counter", egres); job2.getJobDataMap().put(EventmanagerConfiguration.KEY, EventmanagerConfiguration.getInstance()); SimpleTrigger t = (SimpleTrigger) newTrigger().withIdentity("ALFEmitter").startNow().build(); scheduler.scheduleJob(job2, t); @@ -183,6 +213,27 @@ public class MiscServiceServletContextListener implements ServletContextListener } } + private void startEventLogCleaner(Scheduler scheduler) { + try { + if (!scheduler.checkExists(JobKey.jobKey("EventLogCleaner"))) { + JobDetail job2 = JobBuilder.newJob(EventLogCleanerJob.class).withIdentity("EventLogCleaner").build(); + job2.getJobDataMap().put("mdbConnection", mempool); + job2.getJobDataMap().put("fdbConnection", fdbpool); + job2.getJobDataMap().put("run_key", Instant.now().toEpochMilli()); + job2.getJobDataMap().put(EventmanagerConfiguration.KEY, EventmanagerConfiguration.getInstance()); + SimpleTrigger t = (SimpleTrigger) newTrigger().withIdentity("EventLogCleaner") + .withSchedule(SimpleScheduleBuilder.simpleSchedule() + .withIntervalInMinutes(configuration.getCleaner_interval()) + .repeatForever()) + .startAt(Date.from(Instant.now().plus(configuration.getCleaner_interval(), ChronoUnit.MINUTES))) + .build(); + scheduler.scheduleJob(job2, t); + } + } catch (SchedulerException ex) { + log.error("Could not start EventLogCleaner to process existing queue directly after startup: {}", ex.getMessage()); + } + } + private void readConfiguration(ServletContext ctx) { /* Configure ServletContext attributes using configuration object*/ EventmanagerConfiguration c = EventmanagerConfiguration.getInstance().refreshConfig(); diff --git a/src/main/java/net/brutex/xservices/util/SimpleSoap.java b/src/main/java/net/brutex/xservices/util/SimpleSoap.java index 4ed8942..327864d 100644 --- a/src/main/java/net/brutex/xservices/util/SimpleSoap.java +++ b/src/main/java/net/brutex/xservices/util/SimpleSoap.java @@ -22,11 +22,14 @@ import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.EntityBuilder; import org.apache.http.client.fluent.Request; import org.apache.http.client.fluent.Response; +import org.apache.http.entity.ContentType; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.concurrent.atomic.AtomicBoolean; @@ -69,10 +72,12 @@ public class SimpleSoap { public Reader sendSoap(boolean isDropResponse) { Reader response = null; long start = System.currentTimeMillis(); - EntityBuilder entitybuilder = EntityBuilder.create(); - entitybuilder.setContentEncoding("UTF-8"); - entitybuilder.setText(soapBody); - HttpEntity entity = entitybuilder.build(); + + HttpEntity entity = EntityBuilder.create() + .setText(soapBody) + .setContentType(ContentType.create("text/xml", StandardCharsets.UTF_8)) + .setContentEncoding("UTF-8") + .build(); log.trace("Sending event '{}' to target ALF Event Manager.", id); @@ -81,7 +86,7 @@ public class SimpleSoap { try { Response resp = Request.Post(url) .addHeader("Accept", "text/xml") - .addHeader("Content-Type", "text/xml; charset=utf-8") + //.addHeader("Content-Type", "text/xml; charset=utf-8") .addHeader("SOAPAction", "") .body(entity).execute(); diff --git a/src/main/java/net/brutex/xservices/ws/MiscService.java b/src/main/java/net/brutex/xservices/ws/MiscService.java index d8b1cd2..9777792 100644 --- a/src/main/java/net/brutex/xservices/ws/MiscService.java +++ b/src/main/java/net/brutex/xservices/ws/MiscService.java @@ -74,6 +74,7 @@ public interface MiscService { public abstract BigInteger lock(@WebParam(name="id") @XmlElement(nillable = false) String id, @WebParam(name="objectId") @XmlElement(nillable = false) String objectId) throws XServicesFault; - @WebMethod(operationName="EventNotice") - public abstract ALFEventResponseType mergeALFEvent(@WebParam(name="EventNotice", targetNamespace = "http://www.eclipse.org/alf/schema/EventBase/1") ALFEventType event) throws XServicesFault; + @WebMethod(operationName="", action = "EventNotice") + @SOAPBinding(use = SOAPBinding.Use.LITERAL, style = SOAPBinding.Style.DOCUMENT, parameterStyle = SOAPBinding.ParameterStyle.BARE) + public abstract ALFEventResponseType mergeALFEvent(@WebParam(name="ALFEventNoticeDoc", targetNamespace = "http://www.eclipse.org/alf/schema/EventBase/1") ALFEventType event) throws XServicesFault; } diff --git a/src/main/java/net/brutex/xservices/ws/impl/MiscServiceImpl.java b/src/main/java/net/brutex/xservices/ws/impl/MiscServiceImpl.java index 1f72d60..6420065 100644 --- a/src/main/java/net/brutex/xservices/ws/impl/MiscServiceImpl.java +++ b/src/main/java/net/brutex/xservices/ws/impl/MiscServiceImpl.java @@ -41,6 +41,7 @@ import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; +import javax.xml.namespace.QName; import javax.xml.ws.WebServiceContext; import javax.xml.ws.handler.MessageContext; import java.io.StringReader; @@ -59,258 +60,288 @@ import static org.quartz.TriggerBuilder.newTrigger; /** * Implements the web service - * + * * @author Brian Rosenberger, bru@brutex.de */ @Slf4j -@WebService(targetNamespace="http://ws.xservices.brutex.net", endpointInterface="net.brutex.xservices.ws.MiscService", serviceName="MiscService") +@WebService(targetNamespace = "http://ws.xservices.brutex.net", endpointInterface = "net.brutex.xservices.ws.MiscService", serviceName = "MiscService") public class MiscServiceImpl - implements MiscService { + implements MiscService { + + @Resource + private WebServiceContext context; - @Resource - private WebServiceContext context; public MiscServiceImpl() throws SchedulerException { } public HostinfoType getHostinfo(String hostname) { - HostInfo info = new HostInfo(); - info.setTaskName("HostInfo"); - RunTask runner = new RunTask(info); - info.setHost(hostname); + HostInfo info = new HostInfo(); + info.setTaskName("HostInfo"); + RunTask runner = new RunTask(info); + info.setHost(hostname); - ReturnCode ret = runner.postTask(); - HostinfoType infotype = new HostinfoType( - ret.getProperty("NAME"), - ret.getProperty("DOMAIN"), - ret.getProperty("ADDR4"), - ret.getProperty("ADDR6")); - return infotype; - } - - public ReturnCode getInfo() { - ReturnCode r = new ReturnCode(); - r.returnCode = 0; - - Properties props = System.getProperties(); - - Enumeration e = props.propertyNames(); - while (e.hasMoreElements()) { - String propName = (String) e.nextElement(); - - String propValue = (String) props.get(propName); - r.stdOut = (r.stdOut + propName + ": " + propValue + "\n"); + ReturnCode ret = runner.postTask(); + HostinfoType infotype = new HostinfoType( + ret.getProperty("NAME"), + ret.getProperty("DOMAIN"), + ret.getProperty("ADDR4"), + ret.getProperty("ADDR6")); + return infotype; } - return r; - } + public ReturnCode getInfo() { + ReturnCode r = new ReturnCode(); + r.returnCode = 0; - public ReturnCode sendMailSimple(HostConnection mailhost, String from, String tolist, String subject, String message) { - return sendMail(from, from, tolist, "", "", subject, message, - "text/plain", null, mailhost.hostname, mailhost.port, - mailhost.user, mailhost.password, "utf-8", false, false); - } + Properties props = System.getProperties(); - public ReturnCode sendMailSimpleWithAttachment(HostConnection mailhost, String from, String tolist, String subject, String message, FileSetResource res) { - return sendMail(from, from, tolist, "", "", subject, message, - "text/plain", res, mailhost.hostname, mailhost.port, - mailhost.user, mailhost.password, "utf-8", false, false); - } + Enumeration e = props.propertyNames(); + while (e.hasMoreElements()) { + String propName = (String) e.nextElement(); - public ReturnCode sendMail(HostConnection mailhost, String from, String tolist, String cclist, String bcclist, String subject, MailMimeType mimetype, String charset, String message, FileSetResource res, boolean ssl, boolean tls) { - return sendMail(from, from, tolist, cclist, bcclist, subject, message, - mimetype.value(), res, mailhost.hostname, mailhost.port, - mailhost.user, mailhost.password, charset, tls, ssl); - } + String propValue = (String) props.get(propName); + r.stdOut = (r.stdOut + propName + ": " + propValue + "\n"); + } - public ReturnCode sleep(int minutes, int seconds) { - return sleep(0, minutes, seconds, 0); - } - - public String generateUUID() { - return UUID.randomUUID().toString(); - } - - private ReturnCode sendMail(String from, String replyto, String tolist, String cclist, String bcclist, String subject, String message, String messagemimetype, FileSetResource attachments, String mailhost, int mailport, String user, String password, String charset, boolean tls, boolean ssl) { - EmailTask mail = new EmailTask(); - mail.setTaskName("Mail"); - RunTask runner = new RunTask(mail); - mail.setFrom(from); - mail.setReplyTo(replyto); - mail.setToList(tolist); - mail.setCcList(cclist); - mail.setBccList(bcclist); - mail.setSubject(subject); - mail.setMessage(message); - mail.setMessageMimeType(messagemimetype); - if (attachments != null) { - mail.addFileset(attachments.getAntResource(mail.getProject())); - } - mail.setMailhost(mailhost); - mail.setMailport(mailport); - mail.setUser(user); - mail.setPassword(password); - mail.setCharset(charset); - mail.setSSL(ssl); - mail.setEnableStartTLS(tls); - return runner.postTask(); - } - - private ReturnCode sleep(int hours, int minutes, int seconds, int milliseconds) { - Sleep sleep = new Sleep(); - sleep.setTaskName("Sleep"); - RunTask runner = new RunTask(sleep); - sleep.setHours(hours); - sleep.setMinutes(minutes); - sleep.setSeconds(seconds); - sleep.setMilliseconds(milliseconds); - return runner.postTask(); - } - - public RuntimeInfoType getMemory() { - return new RuntimeInfoType(); - } - - @Override - public BigInteger lock(String id, String objectId) throws XServicesFault { - - - - final String conString = "jdbc:h2:mem:lockdb;DB_CLOSE_DELAY=10;" + - "INIT=CREATE SCHEMA IF NOT EXISTS brutex\\;" + - // "SET SCHEMA brutex\\;" + - "CREATE SEQUENCE IF NOT EXISTS brutex.btx_sequence1\\;" + - "CREATE TABLE IF NOT EXISTS brutex.tbl_lock (btx_seq BIGINT NOT NULL, btx_id VARCHAR(100) NOT NULL, btx_obj_id VARCHAR(100) NOT NULL, btx_timestamp BIGINT NOT NULL);"; - - //JdbcConnectionPool cp = JdbcConnectionPool.create(conString, "sa", ""); - //cp.setMaxConnections(1); - - Connection con = null; - long rows = 0L; - final long ts = new Date().getTime(); - try { - Class.forName("org.h2.Driver"); //Java 1.8 - con = DriverManager.getConnection(conString); - PreparedStatement prep = con.prepareStatement( - "SELECT btx_id from brutex.tbl_lock where btx_obj_id=? ORDER BY btx_seq DESC"); - prep.setString(1, objectId); - - ResultSet rs = prep.executeQuery(); - StringBuffer bf = new StringBuffer(); - while (rs.next()) { - //bf.append(rs.getString(1)); - rows++; - } - rs.close(); - - prep = con.prepareStatement("INSERT INTO brutex.tbl_lock values (NEXT VALUE FOR brutex.btx_sequence1, ?, ?, ?)"); - prep.setString(1, id); - prep.setString(2, objectId); - prep.setLong(3, ts); - prep.execute(); - - prep = con.prepareStatement("DELETE from brutex.tbl_lock WHERE btx_timestamp < ?"); - prep.setLong(1, ts - 10000); - prep.execute(); - prep.close(); - - con.close(); - //System.out.println(bf); - } catch (SQLException | ClassNotFoundException e) { - throw new XServicesFault(e); + return r; } - return BigInteger.valueOf(rows); - } - - @Override - public ALFEventResponseType mergeALFEvent(ALFEventType event) throws XServicesFault { - final Instant d = Instant.now(); - final long ts = d.toEpochMilli(); - - //Get Parameters from the Servlet Context - final ServletContext servletContext = - (ServletContext) context.getMessageContext().get(MessageContext.SERVLET_CONTEXT); - final EventmanagerConfiguration conf = (EventmanagerConfiguration) servletContext - .getAttribute(EventmanagerConfiguration.KEY); - - final JdbcConnectionPool pool = (JdbcConnectionPool) servletContext.getAttribute("mdbConnection"); - final JdbcConnectionPool fpool = (JdbcConnectionPool) servletContext.getAttribute("fdbConnection"); - final AtomicLong egres_counter = (AtomicLong) servletContext.getAttribute("egres_counter"); - final AtomicLong ingres_counter = (AtomicLong) servletContext.getAttribute("ingres_counter"); - final Scheduler scheduler = (Scheduler) servletContext.getAttribute("scheduler"); - - log.trace("Read dbConnection from servlet context: {}", pool); - - //System.out.println("Step 2: " + ChronoUnit.MILLIS.between(Instant.now(), d)); - final ObjectFactory of = new ObjectFactory(); - - final String objectId = event.getBase().getObjectId(); - final String eventId = event.getBase().getEventId(); - final String objectType = event.getBase().getObjectType(); - final String eventType = event.getBase().getEventType(); - log.debug("Event id '{}', type '{}' received for object '{}' with object_id '{}'.", - eventId, eventType, objectType, objectId); - - final String mergeStatememt = "MERGE INTO brutex.tbl_events " + - "KEY (btx_event_type, btx_obj_type, btx_obj_id) " + - "VALUES (?,?,?,?,?,?);"; - - - try { - Marshaller m = JAXBContext.newInstance(ALFEventType.class).createMarshaller(); - m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); - m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); - JAXBElement e = of.createEventNotice(event); - StringWriter sw = new StringWriter(); - m.marshal(e, sw); - StringBuilder sb = new StringBuilder(); - sb.append(" \n"); - sb.append("\n"); - sb.append("\n"); - sb.append(sw); - sb.append("\n"); - sb.append(""); - sb.append(""); - - Connection con = pool.getConnection(); - PreparedStatement prep = con.prepareStatement(mergeStatememt); - prep.setString(1, eventType); - prep.setString(2, eventId); - prep.setString(3, objectType); - prep.setString(4, objectId); - prep.setLong(5, ts); - prep.setClob(6, new StringReader(sb.toString())); - prep.execute(); - con.commit(); - con.close(); - - ingres_counter.incrementAndGet(); - - synchronized (scheduler) { - if (!scheduler.checkExists(JobKey.jobKey("ALFEmitter"))) { - JobDetail job2 = JobBuilder.newJob(EventEmitter.class) - .withIdentity("ALFEmitter") - .build(); - job2.getJobDataMap().put("mdbConnection", pool); - job2.getJobDataMap().put("fdbConnection", fpool); - job2.getJobDataMap().put("run_key", ts); - job2.getJobDataMap().put("egres_counter", egres_counter); - job2.getJobDataMap().put("ingres_counter", ingres_counter); - - job2.getJobDataMap().put(EventmanagerConfiguration.KEY, conf); - - SimpleTrigger t = (SimpleTrigger) newTrigger() - .withIdentity("ALFEmitter").startAt(Date.from(d.plusSeconds(conf.getInterval()))) - .build(); - - scheduler.scheduleJob(job2, t); - } - } - } catch (JAXBException | SQLException | SchedulerException e) { - log.error(e.getMessage()); - throw new XServicesFault(e); + public ReturnCode sendMailSimple(HostConnection mailhost, String from, String tolist, String subject, String message) { + return sendMail(from, from, tolist, "", "", subject, message, + "text/plain", null, mailhost.hostname, mailhost.port, + mailhost.user, mailhost.password, "utf-8", false, false); + } + + public ReturnCode sendMailSimpleWithAttachment(HostConnection mailhost, String from, String tolist, String subject, String message, FileSetResource res) { + return sendMail(from, from, tolist, "", "", subject, message, + "text/plain", res, mailhost.hostname, mailhost.port, + mailhost.user, mailhost.password, "utf-8", false, false); + } + + public ReturnCode sendMail(HostConnection mailhost, String from, String tolist, String cclist, String bcclist, String subject, MailMimeType mimetype, String charset, String message, FileSetResource res, boolean ssl, boolean tls) { + return sendMail(from, from, tolist, cclist, bcclist, subject, message, + mimetype.value(), res, mailhost.hostname, mailhost.port, + mailhost.user, mailhost.password, charset, tls, ssl); + } + + public ReturnCode sleep(int minutes, int seconds) { + return sleep(0, minutes, seconds, 0); + } + + public String generateUUID() { + return UUID.randomUUID().toString(); + } + + private ReturnCode sendMail(String from, String replyto, String tolist, String cclist, String bcclist, String subject, String message, String messagemimetype, FileSetResource attachments, String mailhost, int mailport, String user, String password, String charset, boolean tls, boolean ssl) { + EmailTask mail = new EmailTask(); + mail.setTaskName("Mail"); + RunTask runner = new RunTask(mail); + mail.setFrom(from); + mail.setReplyTo(replyto); + mail.setToList(tolist); + mail.setCcList(cclist); + mail.setBccList(bcclist); + mail.setSubject(subject); + mail.setMessage(message); + mail.setMessageMimeType(messagemimetype); + if (attachments != null) { + mail.addFileset(attachments.getAntResource(mail.getProject())); + } + mail.setMailhost(mailhost); + mail.setMailport(mailport); + mail.setUser(user); + mail.setPassword(password); + mail.setCharset(charset); + mail.setSSL(ssl); + mail.setEnableStartTLS(tls); + return runner.postTask(); + } + + private ReturnCode sleep(int hours, int minutes, int seconds, int milliseconds) { + Sleep sleep = new Sleep(); + sleep.setTaskName("Sleep"); + RunTask runner = new RunTask(sleep); + sleep.setHours(hours); + sleep.setMinutes(minutes); + sleep.setSeconds(seconds); + sleep.setMilliseconds(milliseconds); + return runner.postTask(); + } + + public RuntimeInfoType getMemory() { + return new RuntimeInfoType(); + } + + @Override + public BigInteger lock(String id, String objectId) throws XServicesFault { + + + final String conString = "jdbc:h2:mem:lockdb;DB_CLOSE_DELAY=10;" + + "INIT=CREATE SCHEMA IF NOT EXISTS brutex\\;" + + // "SET SCHEMA brutex\\;" + + "CREATE SEQUENCE IF NOT EXISTS brutex.btx_sequence1\\;" + + "CREATE TABLE IF NOT EXISTS brutex.tbl_lock (btx_seq BIGINT NOT NULL, btx_id VARCHAR(100) NOT NULL, btx_obj_id VARCHAR(100) NOT NULL, btx_timestamp BIGINT NOT NULL);"; + + //JdbcConnectionPool cp = JdbcConnectionPool.create(conString, "sa", ""); + //cp.setMaxConnections(1); + + Connection con = null; + long rows = 0L; + final long ts = new Date().getTime(); + try { + Class.forName("org.h2.Driver"); //Java 1.8 + con = DriverManager.getConnection(conString); + PreparedStatement prep = con.prepareStatement( + "SELECT btx_id from brutex.tbl_lock where btx_obj_id=? ORDER BY btx_seq DESC"); + prep.setString(1, objectId); + + ResultSet rs = prep.executeQuery(); + StringBuffer bf = new StringBuffer(); + while (rs.next()) { + //bf.append(rs.getString(1)); + rows++; + } + rs.close(); + + prep = con.prepareStatement("INSERT INTO brutex.tbl_lock values (NEXT VALUE FOR brutex.btx_sequence1, ?, ?, ?)"); + prep.setString(1, id); + prep.setString(2, objectId); + prep.setLong(3, ts); + prep.execute(); + + prep = con.prepareStatement("DELETE from brutex.tbl_lock WHERE btx_timestamp < ?"); + prep.setLong(1, ts - 10000); + prep.execute(); + prep.close(); + + con.close(); + //System.out.println(bf); + } catch (SQLException | ClassNotFoundException e) { + throw new XServicesFault(e); + } + + return BigInteger.valueOf(rows); + } + + @Override + public ALFEventResponseType mergeALFEvent(ALFEventType event) throws XServicesFault { + final Instant d = Instant.now(); + final long ts = d.toEpochMilli(); + + MessageContext cont = context.getMessageContext(); + + //Get Parameters from the Servlet Context + final ServletContext servletContext = + (ServletContext) context.getMessageContext().get(MessageContext.SERVLET_CONTEXT); + final EventmanagerConfiguration conf = (EventmanagerConfiguration) servletContext + .getAttribute(EventmanagerConfiguration.KEY); + + final JdbcConnectionPool pool = (JdbcConnectionPool) servletContext.getAttribute("mdbConnection"); + final JdbcConnectionPool fpool = (JdbcConnectionPool) servletContext.getAttribute("fdbConnection"); + final AtomicLong egres_counter = (AtomicLong) servletContext.getAttribute("egres_counter"); + final AtomicLong ingres_counter = (AtomicLong) servletContext.getAttribute("ingres_counter"); + final Scheduler scheduler = (Scheduler) servletContext.getAttribute("scheduler"); + + log.trace("Read dbConnection from servlet context: {}", pool); + + //System.out.println("Step 2: " + ChronoUnit.MILLIS.between(Instant.now(), d)); + final ObjectFactory of = new ObjectFactory(); + + final String objectId = event.getBase().getObjectId(); + final String eventId = event.getBase().getEventId(); + final String objectType = event.getBase().getObjectType(); + final String eventType = event.getBase().getEventType(); + log.debug("Event id '{}', type '{}' received for object '{}' with object_id '{}'.", + eventId, eventType, objectType, objectId); + + final String mergeStatememt = "SELECT btx_id FROM OLD TABLE (MERGE INTO brutex.tbl_events " + + "KEY (btx_event_type, btx_obj_type, btx_obj_id) " + + "VALUES (?,?,?,?,?,?));"; + + final String insertAll = "INSERT INTO brutex.tbl_events_all VALUES (?,?,?,?,?,?,?)"; + + + try (Connection con = pool.getConnection()) { + Marshaller m = JAXBContext.newInstance(ALFEventType.class).createMarshaller(); + m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); + m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); + JAXBElement e = of.createALFEventNoticeDoc(event); + StringWriter sw = new StringWriter(); + m.marshal(e, sw); + StringBuilder sb = new StringBuilder(); + + sb.append(" \n"); + sb.append("\n"); + + sb.append(sw); + + sb.append(""); + sb.append(""); + + + PreparedStatement prep = con.prepareStatement(mergeStatememt); + prep.setString(1, eventType); + prep.setString(2, eventId); + prep.setString(3, objectType); + prep.setString(4, objectId); + prep.setLong(5, ts); + prep.setClob(6, new StringReader(sb.toString())); + ResultSet r = prep.executeQuery(); + con.commit(); + String supersed_id = null; + if (r.next()) { + supersed_id = r.getString(1); + log.trace("Event '{}' superseded event '{}'", eventId, supersed_id); + } else { + log.trace("Event '{}' inserted into outgoing queue.", eventId); + } + + + /* Write all into permanent storage */ + //Connection fcon = fpool.getConnection(); + prep = con.prepareStatement(insertAll); + prep.setString(1, eventType); + prep.setString(2, eventId); + prep.setString(3, objectType); + prep.setString(4, objectId); + prep.setLong(5, ts); + prep.setString(6, supersed_id); + prep.setClob(7, new StringReader(sb.toString())); + prep.execute(); + + con.commit(); + con.close(); + + ingres_counter.incrementAndGet(); + + if (conf.isEmitterActive()) { + synchronized (scheduler) { + if (!scheduler.checkExists(JobKey.jobKey("ALFEmitter"))) { + JobDetail job2 = JobBuilder.newJob(EventEmitter.class) + .withIdentity("ALFEmitter") + .build(); + job2.getJobDataMap().put("mdbConnection", pool); + job2.getJobDataMap().put("fdbConnection", fpool); + job2.getJobDataMap().put("run_key", ts); + job2.getJobDataMap().put("egres_counter", egres_counter); + job2.getJobDataMap().put("ingres_counter", ingres_counter); + + job2.getJobDataMap().put(EventmanagerConfiguration.KEY, conf); + + SimpleTrigger t = (SimpleTrigger) newTrigger() + .withIdentity("ALFEmitter").startAt(Date.from(d.plusSeconds(conf.getInterval()))) + .build(); + + scheduler.scheduleJob(job2, t); + } + } + } + } catch (JAXBException | SQLException | SchedulerException e) { + log.error(e.getMessage()); + throw new XServicesFault(e); + } + return of.createALFEventResponseType(); } - return of.createALFEventResponseType(); - } } \ No newline at end of file diff --git a/src/main/resources/ddl/BRTX_schema.ddl b/src/main/resources/ddl/BRTX_schema.ddl index b142cd5..2f1dbc1 100644 --- a/src/main/resources/ddl/BRTX_schema.ddl +++ b/src/main/resources/ddl/BRTX_schema.ddl @@ -4,7 +4,7 @@ CREATE SCHEMA IF NOT EXISTS brutex; CREATE TABLE IF NOT EXISTS brutex.tbl_events ( btx_event_type VARCHAR(128) NOT NULL, - btx_id VARCHAR(32) NOT NULL, + btx_id VARCHAR(128) NOT NULL, btx_obj_type VARCHAR(32) NOT NULL, btx_obj_id VARCHAR(32) NOT NULL, btx_timestamp BIGINT NOT NULL, @@ -12,12 +12,13 @@ CREATE TABLE IF NOT EXISTS brutex.tbl_events ); CREATE INDEX IF NOT EXISTS brutex.btx_idx_key ON brutex.tbl_events (btx_obj_id, btx_obj_type, btx_event_type); CREATE INDEX IF NOT EXISTS brutex.btx_idx_ts ON brutex.tbl_events (btx_timestamp ASC); +CREATE INDEX IF NOT EXISTS brutex.btx_idx_id ON brutex.tbl_events (btx_id); CREATE TABLE IF NOT EXISTS brutex.tbl_events_snap ( btx_event_type VARCHAR(128) NOT NULL, - btx_id VARCHAR(32) NOT NULL, + btx_id VARCHAR(128) NOT NULL, btx_obj_type VARCHAR(32) NOT NULL, btx_obj_id VARCHAR(32) NOT NULL, btx_timestamp BIGINT NOT NULL, @@ -30,7 +31,7 @@ CREATE INDEX IF NOT EXISTS brutex.btx_idx_ts ON brutex.tbl_events_snap (btx_time CREATE TABLE IF NOT EXISTS brutex.tbl_events_errors ( btx_event_type VARCHAR(128) NOT NULL, - btx_id VARCHAR(32) NOT NULL, + btx_id VARCHAR(128) NOT NULL, btx_obj_type VARCHAR(32) NOT NULL, btx_obj_id VARCHAR(32) NOT NULL, btx_timestamp BIGINT NOT NULL, @@ -40,3 +41,17 @@ CREATE TABLE IF NOT EXISTS brutex.tbl_events_errors ); CREATE INDEX IF NOT EXISTS brutex.btx_idx_ts ON brutex.tbl_events_errors (btx_timestamp ASC); CREATE INDEX IF NOT EXISTS brutex.btx_idx_retry ON brutex.tbl_events_errors (btx_retry); + +CREATE TABLE IF NOT EXISTS brutex.tbl_events_all +( + btx_event_type VARCHAR(128) NOT NULL, + btx_id VARCHAR(128) NOT NULL, + btx_obj_type VARCHAR(32) NOT NULL, + btx_obj_id VARCHAR(32) NOT NULL, + btx_timestamp BIGINT NOT NULL, + btx_supersed_id VARCHAR(128), + btx_event CLOB +); + +CREATE INDEX IF NOT EXISTS brutex.btx_idx_ssed ON brutex.tbl_events_all (btx_supersed_id); +CREATE INDEX IF NOT EXISTS brutex.btx_idx_ts ON brutex.tbl_events_all (btx_timestamp ASC); \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/data/getEventManagerStatus.sql b/src/main/webapp/WEB-INF/data/getEventManagerStatus.sql new file mode 100644 index 0000000..09bdc79 --- /dev/null +++ b/src/main/webapp/WEB-INF/data/getEventManagerStatus.sql @@ -0,0 +1,10 @@ +select + (select count(*) from MEM_INBOUND) as INBOUND_Queue, + (select count(*) from MEM_OUTBOUND) as OUTBOUND_Queue , + + (select count(*) from mem_all_events) as IN_MEMORY_LOG, + (select count(*) from brutex.tbl_events_all) as FILE_LOG, + (select count(*) from brutex.tbl_events_errors) as ERROR_COUNT, + + ((select count(*) from brutex.tbl_events_all where btx_supersed_id is not null) + (select count(*) from mem_all_events where btx_supersed_id is not null)) as MERGED_EVENTS +FROM DUAL; \ No newline at end of file diff --git a/src/main/resources/eventmanager.properties b/src/main/webapp/WEB-INF/eventmanager.properties similarity index 53% rename from src/main/resources/eventmanager.properties rename to src/main/webapp/WEB-INF/eventmanager.properties index b26df90..3ac9e99 100644 --- a/src/main/resources/eventmanager.properties +++ b/src/main/webapp/WEB-INF/eventmanager.properties @@ -1,6 +1,7 @@ # The target ALF Event Manager to forward processed events to -target.url = http://localhost:8099/ALFEventManager/services/ALFEventManagerSOAP +#target.url = http://localhost:8099/ALFEventManager/services/ALFEventManagerSOAP +target.url = http://localhost:8085/eventmanager/services/ALFEventManagerDocLit # Merging interval in seconds # This specifies the minimum time the service will merge incoming events before starting @@ -18,4 +19,16 @@ memdb = jdbc:h2:mem:lockdb;DB_CLOSE_DELAY=-1; # Embedded file based database (H2 in this case) to use for event persistence # This is the JDBC connection string. # default: fdb = jdbc:h2:file:~/alf_event_db -fdb = jdbc:h2:file:~/alf_event_db \ No newline at end of file +fdb = jdbc:h2:file:~/alf_event_db + + +# Activate Emitter +# Default is true, otherwise XServices will receive events, but not make any attempt to +# forward them. Memory inbound queue will only be written to disk when the service is +# gracefully stopped. +emitter_active = true + +# EventLogCleaner interval in minutes, how often to move all registered events from memory to the file based +# storage. For trace and debugging purpose. Default value is every 5 minutes. A value of zero or smaller +# deactivates the cleaner. Value in minutes. +cleaner_interval = 4 \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index b2127e9..449732e 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -131,16 +131,17 @@ H2Console org.h2.server.web.WebServlet - webAllowOthers - + true - - trace - - - --> + 1