Skip to content

Commit

Permalink
Merge pull request #1 from moqui/master
Browse files Browse the repository at this point in the history
Updating master branch
  • Loading branch information
aabiabdallah authored Oct 4, 2020
2 parents de3f181 + 5c43a59 commit 70f2e8f
Show file tree
Hide file tree
Showing 30 changed files with 596 additions and 96 deletions.
2 changes: 1 addition & 1 deletion framework/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ tasks.withType(JavaCompile) { options.compilerArgs << "-Xlint:deprecation" }
tasks.withType(GroovyCompile) { options.compilerArgs << "-Xlint:unchecked" }
tasks.withType(GroovyCompile) { options.compilerArgs << "-Xlint:deprecation" }

version = '3.0.0-rc5'
version = '3.0.0-rc6'

apply plugin: 'groovy'
apply plugin: 'war'
Expand Down
4 changes: 3 additions & 1 deletion framework/entity/EntityEntities.xml
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,9 @@ along with this software (see the LICENSE.md file). If not, see
exist (for servers where ES data not persisted between restarts)</description></field>
<field name="feedName" type="text-medium"/>
<field name="feedReceiveServiceName" type="text-medium"><description>The service named here should implement the
org.moqui.EntityServices.receive#DataFeed interface.</description></field>
org.moqui.EntityServices.receive#DataFeed interface; defaults in some cases to 'org.moqui.search.SearchServices.index#DataDocuments'</description></field>
<field name="feedDeleteServiceName" type="text-medium"><description>The service named here should implement the
org.moqui.EntityServices.receive#DataFeedDelete interface; defaults in some cases to 'org.moqui.search.SearchServices.delete#DataDocument'</description></field>
<field name="lastFeedStamp" type="date-time"><description>Used only for periodic feeds.</description></field>
<relationship type="one" title="DataFeedType" related="moqui.basic.Enumeration" short-alias="type">
<key-map field-name="dataFeedTypeEnumId"/></relationship>
Expand Down
28 changes: 28 additions & 0 deletions framework/entity/Screen.eecas.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This software is in the public domain under CC0 1.0 Universal plus a
Grant of Patent License.
To the extent possible under law, the author(s) have dedicated all
copyright and related and neighboring rights to this software to the
public domain worldwide. This software is distributed without any
warranty.
You should have received a copy of the CC0 Public Domain Dedication
along with this software (see the LICENSE.md file). If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
-->
<eecas xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/entity-eca-2.1.xsd">
<eeca id="DbFormCache" entity="moqui.screen.form.DbForm" on-create="true" on-update="true" on-delete="true">
<actions><script>ec.cache.getCache('screen.form.db.node').remove(formId)</script></actions></eeca>
<eeca id="DbFormFieldCache" entity="moqui.screen.form.DbFormField" on-create="true" on-update="true" on-delete="true">
<actions><script>ec.cache.getCache('screen.form.db.node').remove(formId)</script></actions></eeca>
<eeca id="DbFormFieldOptionCache" entity="moqui.screen.form.DbFormFieldOption" on-create="true" on-update="true" on-delete="true">
<actions><script>ec.cache.getCache('screen.form.db.node').remove(formId)</script></actions></eeca>
<eeca id="DbFormFieldEntOptsCache" entity="moqui.screen.form.DbFormFieldEntOpts" on-create="true" on-update="true" on-delete="true">
<actions><script>ec.cache.getCache('screen.form.db.node').remove(formId)</script></actions></eeca>
<eeca id="DbFormFieldEntOptsCondCache" entity="moqui.screen.form.DbFormFieldEntOptsCond" on-create="true" on-update="true" on-delete="true">
<actions><script>ec.cache.getCache('screen.form.db.node').remove(formId)</script></actions></eeca>
<eeca id="DbFormFieldEntOptsOrderCache" entity="moqui.screen.form.DbFormFieldEntOptsOrder" on-create="true" on-update="true" on-delete="true">
<actions><script>ec.cache.getCache('screen.form.db.node').remove(formId)</script></actions></eeca>
</eecas>
15 changes: 13 additions & 2 deletions framework/service/org/moqui/EntityServices.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ along with this software (see the LICENSE.md file). If not, see
<service verb="receive" noun="DataFeed" type="interface" no-remember-parameters="true">
<description>Services named in the DataFeed.feedReceiveServiceName field should implement this interface.</description>
<in-parameters>
<parameter name="dataFeedId" required="true"/>
<parameter name="feedStamp" type="Timestamp" required="true"/>
<parameter name="dataFeedId"/>
<parameter name="feedStamp" type="Timestamp"/>
<parameter name="documentList" type="List" required="true">
<parameter name="document" type="Map">
<parameter name="_id" required="true"><description>The combined PK field values of the primary
Expand All @@ -31,6 +31,17 @@ along with this software (see the LICENSE.md file). If not, see
</parameter>
</in-parameters>
</service>
<service verb="receive" noun="DataFeedDelete" type="interface">
<in-parameters>
<parameter name="dataFeedId"/>
<parameter name="feedStamp" type="Timestamp"/>
<parameter name="dataDocumentId" required="true"/>
<parameter name="documentId" required="true"><description>The combined PK field values of the primary
entity in the DataDocument. If there is more than one PK field the values are separated with a
double-colon ("::").</description></parameter>
</in-parameters>
</service>

<service verb="add" noun="ManualDocumentData" type="interface" no-remember-parameters="true">
<description>Services named in the DataDocument.manualDataServiceName field should implement this interface.</description>
<in-parameters>
Expand Down
12 changes: 11 additions & 1 deletion framework/service/org/moqui/impl/BasicServices.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,28 @@ along with this software (see the LICENSE.md file). If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
-->
<services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/service-definition-2.1.xsd">
<service verb="noop" authenticate="anonymous-all" validate="false">
<actions><!-- do nothing, it's a noop service --></actions>
</service>

<!-- ========== Geo Services ========== -->
<service verb="get" noun="GeoRegionsForDropDown" allow-remote="true">
<in-parameters>
<parameter name="geoId"/>
<parameter name="geoAssocTypeEnumId" default-value="GAT_REGIONS"/>
<parameter name="geoTypeEnumId"/>
<parameter name="term"><description>For current Find Options will be only geoId to include in output</description></parameter>
</in-parameters>
<out-parameters><parameter name="resultList" type="List"><parameter name="result" type="Map"/></parameter></out-parameters>
<actions>
<set field="resultList" from="[]"/>
<if condition="geoId">
<if condition="term">
<entity-find-one entity-name="moqui.basic.Geo" value-field="termGeo">
<field-map field-name="geoId" from="term"/></entity-find-one>
<if condition="termGeo != null"><script>resultList.add([geoId:termGeo.geoId, label:(termGeo.geoCodeAlpha2 ? termGeo.geoCodeAlpha2 + ' - ' : '') + termGeo.geoName,
geoName:termGeo.geoName, geoCodeAlpha2:termGeo.geoCodeAlpha2])</script></if>
</if>
<if condition="geoId &amp;&amp; !resultList">
<entity-find entity-name="moqui.basic.GeoAssocAndToDetail" list="geoList">
<econdition field-name="geoId"/><econdition field-name="geoAssocTypeEnumId"/>
<econdition field-name="geoTypeEnumId" ignore-if-empty="true"/>
Expand Down
23 changes: 23 additions & 0 deletions framework/service/org/moqui/search/SearchServices.xml
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,29 @@ along with this software (see the LICENSE.md file). If not, see
</service>
-->

<service verb="delete" noun="DataDocument" authenticate="anonymous-all">
<implements service="org.moqui.EntityServices.receive#DataFeedDelete"/>
<in-parameters>
<parameter name="indexName"/>
<parameter name="dataDocumentId" required="false"><description>For DataFeed compatibility supports dataDocumentId that
if specified is converted to valid ElasticSearch index name instead of using indexName parameter</description></parameter>
<parameter name="documentId" required="true"/>
<parameter name="clusterName" default-value="default"/>
</in-parameters>
<actions><script><![CDATA[
import org.moqui.context.ExecutionContext
import org.moqui.impl.context.ElasticFacadeImpl
ExecutionContext ec = context.ec
// if documentType use instead of indexName to get only specific indexes (split on comma, ddIdToEsIndex, join with comma)
String index = indexName
if (dataDocumentId) index = ((String) dataDocumentId).split(",").collect({ ElasticFacadeImpl.ddIdToEsIndex(it) }).join(",")
def elasticClient = ec.factory.elastic.getClient((String) clusterName)
elasticClient.delete(index, (String) documentId)
]]></script></actions>
</service>

<service verb="delete" noun="Documents" authenticate="anonymous-all" transaction-timeout="1800">
<!-- authenticate=anonymous-all as this is called in a service job, should be exposed through only trusted UI/etc -->
<in-parameters>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import groovy.lang.GString;
import org.jetbrains.annotations.NotNull;
import org.moqui.context.ArtifactExecutionInfo;
import org.moqui.entity.EntityFind;
import org.moqui.entity.EntityList;
Expand Down Expand Up @@ -538,4 +539,69 @@ public WorkerThreadPoolExecutor(ExecutionContextFactoryImpl ecfi, int coreSize,
super.afterExecute(runnable, throwable);
}
}

static class ScheduledThreadFactory implements ThreadFactory {
private final ThreadGroup workerGroup = new ThreadGroup("MoquiScheduled");
private final AtomicInteger threadNumber = new AtomicInteger(1);
public Thread newThread(Runnable r) { return new Thread(workerGroup, r, "MoquiScheduled-" + threadNumber.getAndIncrement()); }
}
static class CustomScheduledTask<V> implements RunnableScheduledFuture<V> {
public final Runnable runnable;
public final Callable<V> callable;
public final RunnableScheduledFuture<V> future;

CustomScheduledTask(Runnable runnable, RunnableScheduledFuture<V> future) {
this.runnable = runnable;
this.callable = null;
this.future = future;
}
CustomScheduledTask(Callable<V> callable, RunnableScheduledFuture<V> future) {
this.runnable = null;
this.callable = callable;
this.future = future;
}

@Override public boolean isPeriodic() { return future.isPeriodic(); }
@Override public long getDelay(@NotNull TimeUnit timeUnit) { return future.getDelay(timeUnit); }
@Override public int compareTo(@NotNull Delayed delayed) { return future.compareTo(delayed); }

@Override public void run() {
try {
// logger.info("Running scheduled task " + toString());
future.run();
} catch (Throwable t) {
logger.error("CustomScheduledTask uncaught Throwable in run(), catching and suppressing so task does not get unscheduled", t);
}
}
@Override public boolean cancel(boolean b) { return future.cancel(b); }
@Override public boolean isCancelled() { return future.isCancelled(); }
@Override public boolean isDone() { return future.isDone(); }

@Override public V get() throws InterruptedException, ExecutionException { return future.get(); }
@Override public V get(long l, @NotNull TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
return get(l, timeUnit); }

@Override public String toString() {
return "CustomScheduledTask " + (runnable != null ? runnable.getClass().getName() : (callable != null ? callable.getClass().getName() : "[no Runnable or Callable!]"));
}
}
static class CustomScheduledExecutor extends ScheduledThreadPoolExecutor {
public CustomScheduledExecutor(int coreThreads) {
super(coreThreads, new ScheduledThreadFactory());
}
protected <V> RunnableScheduledFuture<V> decorateTask(Runnable r, RunnableScheduledFuture<V> task) {
return new CustomScheduledTask<V>(r, task);
}
protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> c, RunnableScheduledFuture<V> task) {
return new CustomScheduledTask<V>(c, task);
}
}
static class ScheduledRunnableInfo {
public final Runnable command;
public final long period;
// NOTE: tracking initial ScheduledFuture is useless as it gets replaced with each run: public final ScheduledFuture scheduledFuture;
ScheduledRunnableInfo(Runnable command, long period) {
this.command = command; this.period = period;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,11 @@ class ElasticFacadeImpl implements ElasticFacade {
if (index == null || index.isEmpty()) throw new IllegalArgumentException("In delete document the index name may not be empty")
if (_id == null || _id.isEmpty()) throw new IllegalArgumentException("In delete document the _id may not be empty")
RestClient.RestResponse response = makeRestClient(Method.DELETE, index + "/_doc/" + _id, null).call()
checkResponse(response, "Delete document ${_id}", index)
if (response.statusCode == 404) {
logger.warn("In delete document not found in index ${index} with ID ${_id}")
} else {
checkResponse(response, "Delete document ${_id}", index)
}
}

@Override
Expand Down Expand Up @@ -621,7 +625,7 @@ class ElasticFacadeImpl implements ElasticFacade {

String requestUri = response.getClient().getUriString()
String requestBody = response.getClient().getBodyText()
if (requestBody.length() > 2000) requestBody = requestBody.substring(0, 2000)
if (requestBody != null && requestBody.length() > 2000) requestBody = requestBody.substring(0, 2000)
logger.error("ElasticSearch ${msg}${responseText ? '\nResponse: ' + responseText : ''}${requestUri ? '\nURI: ' + requestUri : ''}${requestBody ? '\nRequest: ' + requestBody : ''}")

throw new BaseException(msg)
Expand Down
Loading

0 comments on commit 70f2e8f

Please sign in to comment.