Attached Files | 38036-giftcard-5.diff [^] (502 bytes) 2018-03-13 12:27 [Show Content] [Hide Content]diff --git a/src/org/openbravo/retail/giftcards/FindGiftCard.java b/src/org/openbravo/retail/giftcards/FindGiftCard.java
--- a/src/org/openbravo/retail/giftcards/FindGiftCard.java
+++ b/src/org/openbravo/retail/giftcards/FindGiftCard.java
@@ -75,11 +75,6 @@
}
@Override
- protected boolean executeFirstInCentral(JSONObject json) throws JSONException {
- return true;
- }
-
- @Override
protected boolean executeInOneServer(JSONObject json) throws JSONException {
return true;
}
38036-retail-sync-5.diff [^] (46,628 bytes) 2018-03-13 12:27 [Show Content] [Hide Content]diff --git a/src/org/openbravo/retail/storeserver/synchronization/RecomputeVersionModuleHandler.java b/src/org/openbravo/retail/storeserver/synchronization/RecomputeVersionModuleHandler.java
--- a/src/org/openbravo/retail/storeserver/synchronization/RecomputeVersionModuleHandler.java
+++ b/src/org/openbravo/retail/storeserver/synchronization/RecomputeVersionModuleHandler.java
@@ -46,9 +46,4 @@
}
return response;
}
-
- @Override
- protected boolean ignoreTransitioningStatus() {
- return true;
- }
}
diff --git a/src/org/openbravo/retail/storeserver/synchronization/RetailSynchronizationRequestAllowedHandler.java b/src/org/openbravo/retail/storeserver/synchronization/RetailSynchronizationRequestAllowedHandler.java
deleted file mode 100644
--- a/src/org/openbravo/retail/storeserver/synchronization/RetailSynchronizationRequestAllowedHandler.java
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- *************************************************************************
- * Openbravo DB Synchronization module for Retail
- * Copyright (C) 2017 Openbravo SLU
- *
- * The content of this file is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- ************************************************************************
- */
-
-package org.openbravo.retail.storeserver.synchronization;
-
-import java.io.BufferedReader;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import javax.enterprise.event.Observes;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.log4j.Logger;
-import org.codehaus.jettison.json.JSONObject;
-import org.jfree.util.Log;
-import org.openbravo.base.exception.OBException;
-import org.openbravo.base.model.Entity;
-import org.openbravo.base.model.ModelProvider;
-import org.openbravo.client.kernel.event.EntityDeleteEvent;
-import org.openbravo.client.kernel.event.EntityNewEvent;
-import org.openbravo.client.kernel.event.EntityPersistenceEventObserver;
-import org.openbravo.client.kernel.event.EntityUpdateEvent;
-import org.openbravo.dal.core.OBContext;
-import org.openbravo.dal.service.OBDal;
-import org.openbravo.mobile.core.MobileServerDefinition;
-import org.openbravo.mobile.core.process.MobileService.MobileServiceRequestAllowedHandler;
-import org.openbravo.mobile.core.servercontroller.MobileServerController;
-import org.openbravo.mobile.core.servercontroller.MobileServerRequestExecutor;
-import org.openbravo.mobile.core.servercontroller.MobileServerState;
-import org.openbravo.mobile.core.servercontroller.MobileServerStatusInformation;
-import org.openbravo.mobile.core.servercontroller.MobileServerUtils;
-import org.openbravo.mobile.core.utils.OBMOBCUtils;
-import org.openbravo.replication.symmetricds.diagnosis.RemoteStoreServerDiagnosisProcess;
-import org.openbravo.retail.storeserver.synchronization.eventhandler.MobileServerEventHandler;
-
-import com.google.common.net.HttpHeaders;
-
-/**
- * Prevents requests from happening if the server is reloading or forwards requests to the central server or in another way in a state which
- * does not allow WebPOS connections.
- *
- * @author Martin Taal
- */
-public class RetailSynchronizationRequestAllowedHandler extends MobileServiceRequestAllowedHandler {
-
- private static final Logger log = Logger.getLogger(RetailSynchronizationRequestAllowedHandler.class);
-
- // on purpose static to let it be nullified by eventhandler
- private static Collection<String> domainRegExList = null;
- private static Set<String> allowedReferers = new HashSet<String>();
-
- @Override
- public boolean allowRequest(HttpServletRequest request, HttpServletResponse response) {
- // do not check reload/version status if a central server
- if (MobileServerController.getInstance().isThisACentralServer()) {
- return true;
- }
-
- MobileServerDefinition thisServerDefinition = MobileServerController.getInstance()
- .getThisServerDefinition();
-
- if (thisServerDefinition == null) {
- return true;
- }
-
- if (!MobileServerUtils.isMultiServerEnabled()) {
- return true;
- }
-
- // always allow ping service
- if (isAllowedService(request)) {
- return true;
- }
-
- if (isMandatoryReload(thisServerDefinition)) {
- writeResponseJSON(response, "RELOADING");
- return false;
- }
-
- final boolean isOffline = thisServerDefinition.getStatus().equals(MobileServerState.OFFLINE.getValue());
- if (isOffline && MobileServerController.getInstance().isThisAStoreServer() && thisServerDefinition.isOfflineIncomingErrors() && MobileServerEventHandler.doIncomingSyncErrorsExist()) {
- // send back invalid offline status
- writeResponseJSON(response, "INVALID_OFFLINE");
- return false;
- }
-
- if (forwardedToCentralServer(request, response)) {
- return false;
- }
-
- if (isOffline && !isRequestRefererFromThisServer(request)
- && !StoreServerVersionHandler.getInstance().areCentralStoreServerVersionsCompatible()) {
- // send back incompat status
- try {
- // special case, if there are batches pending to sync then webpos is not allowed to work on
- // central
- // either, in that case direct the user to use a different url
- if (RetrieveSyncStatus.countBatchesPendingToSyncToCentral() > 0) {
- writeResponseJSON(response, "INCOMPATIBLE_VERSION_DATA_PENDING_TO_SYNC");
- return false;
- }
-
- writeResponseJSON(response, "INCOMPATIBLE_VERSION");
- } catch (Throwable t) {
- throw new OBException(t);
- }
- return false;
- }
-
- // allow all other cases
- return true;
- }
-
- private boolean isMandatoryReload(MobileServerDefinition sd) {
- return "MANDATORY_RELOADING".equals(sd.getStrsyncReloadStatus())
- || "MANDATORY_ON_STARTUP".equals(sd.getStrsyncReloadStatus());
- }
-
- private void writeResponseJSON(HttpServletResponse response, String serverStatusSignal) {
- try {
- final JSONObject json = new JSONObject();
- final JSONObject responseJson = new JSONObject();
- json.put("serverStatusSignal", serverStatusSignal);
- responseJson.put("response", json);
- final Writer w = response.getWriter();
- w.write(responseJson.toString());
- w.close();
- } catch (Throwable t) {
- throw new OBException(t);
- }
- }
-
- private boolean isAllowedService(HttpServletRequest request) {
- if (request.getRequestURL().toString().contains(MobileServerStatusInformation.class.getName())) {
- return true;
- }
- if (request.getRequestURL().toString().contains(RetrieveServerVersionStatus.class.getName())) {
- return true;
- }
- if (request.getRequestURL().toString()
- .contains(RemoteStoreServerDiagnosisProcess.class.getName())) {
- return true;
- }
- if (request.getRequestURL().toString().contains(RecomputeVersionModuleHandler.class.getName())) {
- return true;
- }
-
- return false;
- }
-
- private boolean forwardedToCentralServer(HttpServletRequest request, HttpServletResponse response) {
- try {
- // don't let the CS forward to itself
- if (MobileServerController.getInstance().isThisACentralServer()) {
- return false;
- }
-
- // only forward to CS if online
- if (!MobileServerController.getInstance().getThisMobileServerState().equals(MobileServerState.ONLINE)) {
- return false;
- }
-
- // only handle it here if the request is from webpos
- // use querystring to prevent null content
- final String qs = request.getQueryString();
- boolean sourceWebPOS = !qs.contains(MobileServerRequestExecutor.SOURCE_PROP);
- sourceWebPOS |= qs.contains(MobileServerRequestExecutor.SOURCE_PROP + "=" + MobileServerRequestExecutor.SOURCE_WEBPOS);
- if (sourceWebPOS) {
- final String content = getRequestContent(request);
- final String requestPath = request.getRequestURI().substring(request.getContextPath().length()) + "?" + request.getQueryString();
- final JSONObject requestContent = content == null || content.length() == 0 ? null : new JSONObject(content);
- JSONObject result = null;
- try {
- result = MobileServerRequestExecutor.getInstance().executeCentralRequest(requestPath,
- requestContent);
- } catch (Throwable t) {
- result = handleCentralServerRequestException(t);
- }
-
- response.setContentType("application/json");
- response.setCharacterEncoding("UTF-8");
-
- final Writer w = response.getWriter();
- w.write("{\"response\":");
- w.write(result.toString());
- w.write("}");
- w.close();
- return true;
- }
- // offline --> is handled by request allowed handlers
- // transitioning states --> let the service handle it as some services need to be callable in transition state also
- return false;
- } catch (Exception e) {
- throw new OBException("Error when handling request " + request.getPathInfo(), e);
- }
- }
-
- private JSONObject handleCentralServerRequestException(Throwable t) throws Exception {
- log.error(t.getMessage(), t);
-
- OBContext.setAdminMode(false);
- try {
- // set the central server as not being reachable
- final MobileServerDefinition centralServer = MobileServerController.getInstance()
- .getCentralServer();
- centralServer.setStatus(MobileServerState.OFFLINE.getValue());
- OBDal.getInstance().save(centralServer);
- } finally {
- OBContext.restorePreviousMode();
- }
-
- if (!MobileServerState.TRANSITION_TO_OFFLINE.equals(MobileServerController.getInstance()
- .getThisMobileServerState())) {
- // transition to offline,
- // which causes the next if to be executed
- log.info("Could not communicate with the central server, starting transition to offline");
- MobileServerController.getInstance().transitionToOffline();
- }
-
- if (MobileServerController.getInstance().serverHasTransitioningStatus()) {
- final JSONObject result = new JSONObject();
- MobileServerController.getInstance().setServerStatusJSON(result);
- return result;
- }
-
- // return a exception json, the transaction will be committed is fine
- // as the central server will move to offline so database action
- // happened
- return OBMOBCUtils.createSimpleErrorJson("OBMOBC_MsgCentralServerNotAvailable");
- }
-
- private String getRequestContent(HttpServletRequest request) throws Exception {
- final BufferedReader reader = request.getReader();
- if (reader == null) {
- return null;
- }
- String line;
- final StringBuilder sb = new StringBuilder();
- while ((line = reader.readLine()) != null) {
- if (sb.length() > 0) {
- sb.append("\n");
- }
- sb.append(line);
- }
- return sb.toString();
- }
-
- public boolean isRequestRefererFromThisServer(HttpServletRequest request) {
- String referer = request.getHeader(HttpHeaders.REFERER);
-
- if (referer == null) {
- return false;
- }
-
- // do some repairs on the referer to only get the host part
- int index = referer.indexOf("//");
- index = referer.indexOf("/", index + 2);
- if (index == -1) {
- index = referer.length();
- }
- referer = referer.substring(0, index);
-
- if (domainRegExList == null) {
- buildDomainList();
- }
-
- if (allowedReferers.contains(referer)) {
- return true;
- }
-
- if (domainRegExList.isEmpty()) {
- return false;
- }
-
- for (String domainRegEx : domainRegExList) {
- // matches is 5 times slower than precompile regex
- // but as we cache allowed domains anyway (see allowedDomains set)
- // there is less need to optimize
- if (referer.matches(domainRegEx)) {
- allowedReferers.add(referer);
- return true;
- }
- }
-
- return false;
- }
-
- private synchronized void buildDomainList() {
- allowedReferers = new HashSet<String>();
-
- if (!MobileServerUtils.isMultiServerEnabled()) {
- domainRegExList = new ArrayList<String>();
- return;
- }
-
- final Collection<String> localDomainList = new ArrayList<String>();
- localDomainList.addAll(getAllowedDomains(MobileServerController.getInstance()
- .getThisServerDefinition()));
- domainRegExList = localDomainList;
- }
-
- private List<String> getAllowedDomains(MobileServerDefinition serverDefinition) {
- final List<String> result = new ArrayList<String>();
- if (serverDefinition.getURL() != null) {
- result.add(getAllowedOriginExp(serverDefinition.getURL()));
- }
- if (serverDefinition.getAlloweddomains() != null) {
- String tmpDomains = serverDefinition.getAlloweddomains();
- // support line breaks instead of commas, support all the platforms
- // as the browser may run in different OS on the client side
- tmpDomains = tmpDomains.replace("\r\n", ",");
- tmpDomains = tmpDomains.replace("\n", ",");
- tmpDomains = tmpDomains.replace("\r", ",");
- // all the separators are now commas, split on it
- final String[] domains = tmpDomains.split(",");
- for (String domain : domains) {
- String regEx = getAllowedOriginExp(domain.trim());
- // test the regEx
- try {
- Pattern.compile(regEx);
- result.add(regEx);
- } catch (Exception logIt) {
- Log.error("Reg ex " + regEx + " does not compile " + logIt.getMessage(), logIt);
- }
- }
- }
- return result;
- }
-
- private String getAllowedOriginExp(String url) {
- // note url can contain dots, but on purpose not escaping those
- // to allow flexibility, if the user wants explicit dots he/she
- // should escape them
-
- String localUrl = url.toLowerCase();
- int nextIndex = 2 + localUrl.indexOf("//");
- if (localUrl.indexOf("/", nextIndex) == -1) {
- return localUrl;
- }
- localUrl = localUrl.substring(0, localUrl.indexOf("/", nextIndex));
- return localUrl;
- }
-
- /**
- * Clear the cache when a mobile server definition is saved.
- */
- public static class MobileServerDefinitionEventHandler extends EntityPersistenceEventObserver {
-
- private static Entity[] entities = { ModelProvider.getInstance().getEntity(
- MobileServerDefinition.ENTITY_NAME) };
- protected Logger logger = Logger.getLogger(this.getClass());
-
- @Override
- protected Entity[] getObservedEntities() {
- return entities;
- }
-
- public void onSave(@Observes EntityNewEvent event) {
- if (!isValidEvent(event)) {
- return;
- }
- domainRegExList = null;
- }
-
- public void onUpdate(@Observes EntityUpdateEvent event) {
- if (!isValidEvent(event)) {
- return;
- }
- domainRegExList = null;
- }
-
- public void onDelete(@Observes EntityDeleteEvent event) {
- if (!isValidEvent(event)) {
- return;
- }
- domainRegExList = null;
- }
- }
-
-}
diff --git a/src/org/openbravo/retail/storeserver/synchronization/RetailSynchronizationRequestHandler.java b/src/org/openbravo/retail/storeserver/synchronization/RetailSynchronizationRequestHandler.java
new file mode 100644
--- /dev/null
+++ b/src/org/openbravo/retail/storeserver/synchronization/RetailSynchronizationRequestHandler.java
@@ -0,0 +1,421 @@
+/*
+ *************************************************************************
+ * Openbravo DB Synchronization module for Retail
+ * Copyright (C) 2018 Openbravo SLU
+ *
+ * The content of this file is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ ************************************************************************
+ */
+
+package org.openbravo.retail.storeserver.synchronization;
+
+import java.io.BufferedReader;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import javax.enterprise.event.Observes;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+import org.codehaus.jettison.json.JSONObject;
+import org.jfree.util.Log;
+import org.openbravo.base.exception.OBException;
+import org.openbravo.base.model.Entity;
+import org.openbravo.base.model.ModelProvider;
+import org.openbravo.client.kernel.event.EntityDeleteEvent;
+import org.openbravo.client.kernel.event.EntityNewEvent;
+import org.openbravo.client.kernel.event.EntityPersistenceEventObserver;
+import org.openbravo.client.kernel.event.EntityUpdateEvent;
+import org.openbravo.dal.core.OBContext;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.mobile.core.MobileServerDefinition;
+import org.openbravo.mobile.core.process.MobileService.MobileServiceRequestHandler;
+import org.openbravo.mobile.core.servercontroller.MobileServerController;
+import org.openbravo.mobile.core.servercontroller.MobileServerRequestExecutor;
+import org.openbravo.mobile.core.servercontroller.MobileServerState;
+import org.openbravo.mobile.core.servercontroller.MobileServerStatusInformation;
+import org.openbravo.mobile.core.servercontroller.MobileServerUtils;
+import org.openbravo.mobile.core.utils.OBMOBCUtils;
+import org.openbravo.replication.symmetricds.diagnosis.RemoteStoreServerDiagnosisProcess;
+import org.openbravo.retail.storeserver.synchronization.eventhandler.MobileServerEventHandler;
+
+import com.google.common.net.HttpHeaders;
+
+/**
+ * Prevents requests from happening if the server is reloading or forwards requests to the central server or in another way in a
+ * state which does not allow WebPOS connections.
+ *
+ * @author Martin Taal
+ */
+public class RetailSynchronizationRequestHandler extends MobileServiceRequestHandler {
+
+ private static final Logger log = Logger.getLogger(RetailSynchronizationRequestHandler.class);
+
+ // on purpose static to let it be nullified by eventhandler
+ private static Collection<String> domainRegExList = null;
+ private static Set<String> allowedReferers = new HashSet<String>();
+
+ @Override
+ public boolean requestHandled(HttpServletRequest request, HttpServletResponse response) {
+ // CS code should be done in standard way
+ if (MobileServerController.getInstance().isThisACentralServer()) {
+ return false;
+ }
+
+ // no multi-server, do not handle here
+ if (!MobileServerUtils.isMultiServerEnabled()) {
+ return false;
+ }
+
+ MobileServerDefinition thisServerDefinition = MobileServerController.getInstance()
+ .getThisServerDefinition();
+ // no multi-server, do not handle here
+ if (thisServerDefinition == null) {
+ return false;
+ }
+
+ if (doNotHandleServiceHere(request)) {
+ return false;
+ }
+
+ // handle mandatory reload here
+ if (isMandatoryReload(thisServerDefinition)) {
+ writeResponseJSON(response, "RELOADING");
+ return true;
+ }
+
+ // transitioning do not allow any other requests
+ if (MobileServerController.getInstance().serverHasTransitioningStatus()) {
+ writeResponseJSON(response, MobileServerController.getInstance().getThisMobileServerState()
+ .getValue());
+ return true;
+ }
+
+ // handle invalid offline here
+ final boolean isOffline = thisServerDefinition.getStatus().equals(
+ MobileServerState.OFFLINE.getValue());
+ if (isOffline && MobileServerController.getInstance().isThisAStoreServer()
+ && thisServerDefinition.isOfflineIncomingErrors()
+ && MobileServerEventHandler.doIncomingSyncErrorsExist()) {
+ // send back invalid offline status
+ writeResponseJSON(response, "INVALID_OFFLINE");
+ return false;
+ }
+
+ // try forward to CS
+ if (forwardedToCentralServer(request, response)) {
+ return true;
+ }
+
+ if (isOffline && !isRequestRefererFromThisServer(request)
+ && !StoreServerVersionHandler.getInstance().areCentralStoreServerVersionsCompatible()) {
+ // send back incompat status
+ try {
+ // special case, if there are batches pending to sync then webpos is not allowed to work on
+ // central
+ // either, in that case direct the user to use a different url
+ if (RetrieveSyncStatus.countBatchesPendingToSyncToCentral() > 0) {
+ writeResponseJSON(response, "INCOMPATIBLE_VERSION_DATA_PENDING_TO_SYNC");
+ return true;
+ }
+
+ writeResponseJSON(response, "INCOMPATIBLE_VERSION");
+ } catch (Throwable t) {
+ throw new OBException(t);
+ }
+ return true;
+ }
+
+ // all other cases are done by the MobileService
+ return false;
+ }
+
+ private boolean isMandatoryReload(MobileServerDefinition sd) {
+ return "MANDATORY_RELOADING".equals(sd.getStrsyncReloadStatus())
+ || "MANDATORY_ON_STARTUP".equals(sd.getStrsyncReloadStatus());
+ }
+
+ private void writeResponseJSON(HttpServletResponse response, String serverStatusSignal) {
+ try {
+ final JSONObject json = new JSONObject();
+ final JSONObject responseJson = new JSONObject();
+ json.put("serverStatusSignal", serverStatusSignal);
+ responseJson.put("response", json);
+ final Writer w = response.getWriter();
+ w.write(responseJson.toString());
+ w.close();
+ } catch (Throwable t) {
+ throw new OBException(t);
+ }
+ }
+
+ private boolean doNotHandleServiceHere(HttpServletRequest request) {
+ if (request.getRequestURL().toString().contains(MobileServerStatusInformation.class.getName())) {
+ return true;
+ }
+ if (request.getRequestURL().toString().contains(RetrieveServerVersionStatus.class.getName())) {
+ return true;
+ }
+ if (request.getRequestURL().toString()
+ .contains(RemoteStoreServerDiagnosisProcess.class.getName())) {
+ return true;
+ }
+ if (request.getRequestURL().toString().contains(RecomputeVersionModuleHandler.class.getName())) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean forwardedToCentralServer(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ // don't let the CS forward to itself
+ if (MobileServerController.getInstance().isThisACentralServer()) {
+ return false;
+ }
+
+ // only forward to CS if online
+ if (!MobileServerController.getInstance().getThisMobileServerState()
+ .equals(MobileServerState.ONLINE)) {
+ return false;
+ }
+
+ // only handle it here if the request is from webpos
+ // use querystring to prevent null content
+ final String qs = request.getQueryString();
+ boolean sourceWebPOS = qs == null || !qs.contains(MobileServerRequestExecutor.SOURCE_PROP);
+ sourceWebPOS |= qs != null
+ && qs.contains(MobileServerRequestExecutor.SOURCE_PROP + "="
+ + MobileServerRequestExecutor.SOURCE_WEBPOS);
+ if (sourceWebPOS) {
+ final String content = getRequestContent(request);
+ final String requestPath = request.getRequestURI().substring(
+ request.getContextPath().length())
+ + "?" + (qs != null ? qs : "");
+ final JSONObject requestContent = content == null || content.length() == 0 ? null
+ : new JSONObject(content);
+ JSONObject result = null;
+ try {
+ result = MobileServerRequestExecutor.getInstance().executeCentralRequest(requestPath,
+ requestContent);
+ } catch (Throwable t) {
+ result = handleCentralServerRequestException(t);
+ }
+
+ response.setContentType("application/json");
+ response.setCharacterEncoding("UTF-8");
+
+ final Writer w = response.getWriter();
+ w.write("{\"response\":");
+ w.write(result.toString());
+ w.write("}");
+ w.close();
+ return true;
+ }
+ // not from webpos, handle locally
+ return false;
+ } catch (Exception e) {
+ throw new OBException("Error when handling request " + request.getPathInfo(), e);
+ }
+ }
+
+ private JSONObject handleCentralServerRequestException(Throwable t) throws Exception {
+ log.error(t.getMessage(), t);
+
+ OBContext.setAdminMode(false);
+ try {
+ // set the central server as not being reachable
+ final MobileServerDefinition centralServer = MobileServerController.getInstance()
+ .getCentralServer();
+ centralServer.setStatus(MobileServerState.OFFLINE.getValue());
+ OBDal.getInstance().save(centralServer);
+ } finally {
+ OBContext.restorePreviousMode();
+ }
+
+ if (!MobileServerState.TRANSITION_TO_OFFLINE.equals(MobileServerController.getInstance()
+ .getThisMobileServerState())) {
+ // transition to offline,
+ // which causes the next if to be executed
+ log.info("Could not communicate with the central server, starting transition to offline");
+ MobileServerController.getInstance().transitionToOffline();
+ }
+
+ if (MobileServerController.getInstance().serverHasTransitioningStatus()) {
+ final JSONObject result = new JSONObject();
+ MobileServerController.getInstance().setServerStatusJSON(result);
+ return result;
+ }
+
+ // return a exception json, the transaction will be committed is fine
+ // as the central server will move to offline so database action
+ // happened
+ return OBMOBCUtils.createSimpleErrorJson("OBMOBC_MsgCentralServerNotAvailable");
+ }
+
+ private String getRequestContent(HttpServletRequest request) throws Exception {
+ final BufferedReader reader = request.getReader();
+ if (reader == null) {
+ return null;
+ }
+ String line;
+ final StringBuilder sb = new StringBuilder();
+ while ((line = reader.readLine()) != null) {
+ if (sb.length() > 0) {
+ sb.append("\n");
+ }
+ sb.append(line);
+ }
+ return sb.toString();
+ }
+
+ public boolean isRequestRefererFromThisServer(HttpServletRequest request) {
+ String referer = request.getHeader(HttpHeaders.REFERER);
+
+ if (referer == null) {
+ return false;
+ }
+
+ // do some repairs on the referer to only get the host part
+ int index = referer.indexOf("//");
+ index = referer.indexOf("/", index + 2);
+ if (index == -1) {
+ index = referer.length();
+ }
+ referer = referer.substring(0, index);
+
+ if (domainRegExList == null) {
+ buildDomainList();
+ }
+
+ if (allowedReferers.contains(referer)) {
+ return true;
+ }
+
+ if (domainRegExList.isEmpty()) {
+ return false;
+ }
+
+ for (String domainRegEx : domainRegExList) {
+ // matches is 5 times slower than precompile regex
+ // but as we cache allowed domains anyway (see allowedDomains set)
+ // there is less need to optimize
+ if (referer.matches(domainRegEx)) {
+ allowedReferers.add(referer);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private synchronized void buildDomainList() {
+ allowedReferers = new HashSet<String>();
+
+ if (!MobileServerUtils.isMultiServerEnabled()) {
+ domainRegExList = new ArrayList<String>();
+ return;
+ }
+
+ final Collection<String> localDomainList = new ArrayList<String>();
+ localDomainList.addAll(getAllowedDomains(MobileServerController.getInstance()
+ .getThisServerDefinition()));
+ domainRegExList = localDomainList;
+ }
+
+ private List<String> getAllowedDomains(MobileServerDefinition serverDefinition) {
+ final List<String> result = new ArrayList<String>();
+ if (serverDefinition.getURL() != null) {
+ result.add(getAllowedOriginExp(serverDefinition.getURL()));
+ }
+ if (serverDefinition.getAlloweddomains() != null) {
+ String tmpDomains = serverDefinition.getAlloweddomains();
+ // support line breaks instead of commas, support all the platforms
+ // as the browser may run in different OS on the client side
+ tmpDomains = tmpDomains.replace("\r\n", ",");
+ tmpDomains = tmpDomains.replace("\n", ",");
+ tmpDomains = tmpDomains.replace("\r", ",");
+ // all the separators are now commas, split on it
+ final String[] domains = tmpDomains.split(",");
+ for (String domain : domains) {
+ String regEx = getAllowedOriginExp(domain.trim());
+ // test the regEx
+ try {
+ Pattern.compile(regEx);
+ result.add(regEx);
+ } catch (Exception logIt) {
+ Log.error("Reg ex " + regEx + " does not compile " + logIt.getMessage(), logIt);
+ }
+ }
+ }
+ return result;
+ }
+
+ private String getAllowedOriginExp(String url) {
+ // note url can contain dots, but on purpose not escaping those
+ // to allow flexibility, if the user wants explicit dots he/she
+ // should escape them
+
+ String localUrl = url.toLowerCase();
+ int nextIndex = 2 + localUrl.indexOf("//");
+ if (localUrl.indexOf("/", nextIndex) == -1) {
+ return localUrl;
+ }
+ localUrl = localUrl.substring(0, localUrl.indexOf("/", nextIndex));
+ return localUrl;
+ }
+
+ /**
+ * Clear the cache when a mobile server definition is saved.
+ */
+ public static class MobileServerDefinitionEventHandler extends EntityPersistenceEventObserver {
+
+ private static Entity[] entities = { ModelProvider.getInstance().getEntity(
+ MobileServerDefinition.ENTITY_NAME) };
+ protected Logger logger = Logger.getLogger(this.getClass());
+
+ @Override
+ protected Entity[] getObservedEntities() {
+ return entities;
+ }
+
+ public void onSave(@Observes EntityNewEvent event) {
+ if (!isValidEvent(event)) {
+ return;
+ }
+ domainRegExList = null;
+ }
+
+ public void onUpdate(@Observes EntityUpdateEvent event) {
+ if (!isValidEvent(event)) {
+ return;
+ }
+ domainRegExList = null;
+ }
+
+ public void onDelete(@Observes EntityDeleteEvent event) {
+ if (!isValidEvent(event)) {
+ return;
+ }
+ domainRegExList = null;
+ }
+ }
+
+}
diff --git a/src/org/openbravo/retail/storeserver/synchronization/RetrieveServerVersionStatus.java b/src/org/openbravo/retail/storeserver/synchronization/RetrieveServerVersionStatus.java
--- a/src/org/openbravo/retail/storeserver/synchronization/RetrieveServerVersionStatus.java
+++ b/src/org/openbravo/retail/storeserver/synchronization/RetrieveServerVersionStatus.java
@@ -39,11 +39,6 @@
public class RetrieveServerVersionStatus extends JSONProcessSimple {
@Override
- protected boolean ignoreTransitioningStatus() {
- return true;
- }
-
- @Override
public JSONObject exec(JSONObject jsonSent) throws JSONException, ServletException {
final MobileServerDefinition thisServer = MobileServerController.getInstance()
.getThisServerDefinition();
diff --git a/src/org/openbravo/retail/storeserver/synchronization/StoreServerVersionHandler.java b/src/org/openbravo/retail/storeserver/synchronization/StoreServerVersionHandler.java
--- a/src/org/openbravo/retail/storeserver/synchronization/StoreServerVersionHandler.java
+++ b/src/org/openbravo/retail/storeserver/synchronization/StoreServerVersionHandler.java
@@ -1,7 +1,7 @@
/*
*************************************************************************
* Openbravo DB Synchronization module for Retail
- * Copyright (C) 2017 Openbravo SLU
+ * Copyright (C) 2018 Openbravo SLU
*
* The content of this file is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -43,38 +43,33 @@
import org.slf4j.LoggerFactory;
/**
- * Class which manages store server versions and version checks to prevent servers in different
- * versions to exchange information.
+ * Class which manages store server versions and version checks to prevent servers in different versions to exchange information.
*
- * Some background information: - when a server starts the system checks if modules have been
- * installed/updated - if this is the case then the server will regenerate the modules-by-server
- * table for this server and compute - a new version number - the list of modules by server are
- * replicated, from a store to central, and for the central server (so the modules of the central
- * server) to all stores.
+ * Some background information: - when a server starts the system checks if modules have been installed/updated - if this is the
+ * case then the server will regenerate the modules-by-server table for this server and compute - a new version number - the list
+ * of modules by server are replicated, from a store to central, and for the central server (so the modules of the central server)
+ * to all stores.
*
* For the central and store server there are different consequences.
*
- * If the central server modules change then the new module list is replicated to all store servers.
- * The {@link VersionCacheResetWriterFilterAdapter} class runs in the store server and listens to
- * this replication. If the central server modules change then automatically the store server
- * version information is recomputed/checked against the new central server version. If the store
- * and central server have different versions for the same modules then the store server will move
- * to offline and to the Different-From-Central version status.
+ * If the central server modules change then the new module list is replicated to all store servers. The
+ * {@link VersionCacheResetWriterFilterAdapter} class runs in the store server and listens to this replication. If the central
+ * server modules change then automatically the store server version information is recomputed/checked against the new central
+ * server version. If the store and central server have different versions for the same modules then the store server will move to
+ * offline and to the Different-From-Central version status.
*
- * If the store server modules change then the store server will recompute its version and replicate
- * its modules-by-server to the central server.
+ * If the store server modules change then the store server will recompute its version and replicate its modules-by-server to the
+ * central server.
*
- * There is also a writer adapter {@link PreferenceWriterFilterAdapter} which listens to replication
- * of the writer filter adapter from the central to the store server. If the ignore-version-check
- * preference changes then the store servers version status is recomputed also.
+ * There is also a writer adapter {@link PreferenceWriterFilterAdapter} which listens to replication of the writer filter adapter
+ * from the central to the store server. If the ignore-version-check preference changes then the store servers version status is
+ * recomputed also.
*
- * When the store server is incompatible with the central server then the
- * {@link StoreServerIncomingSynchronizationPreventer} will prevent data to be replicated from
- * central to the store.
+ * When the store server is incompatible with the central server then the {@link StoreServerIncomingSynchronizationPreventer} will
+ * prevent data to be replicated from central to the store.
*
- * The {@link RetailSynchronizationRequestAllowedHandler} plays a role in preventing a webpos which
- * is not loaded from the store server to connect to the store server if the store/central server
- * have different versions.
+ * The {@link RetailSynchronizationRequestHandler} plays a role in preventing a webpos which is not loaded from the store server
+ * to connect to the store server if the store/central server have different versions.
*
* @author mtaal
*/
@@ -120,9 +115,8 @@
}
/**
- * Returns true if the caller should take into account if the store and central server have
- * different versions. Returns false in other cases, for example if the ignore version differences
- * preference is set.
+ * Returns true if the caller should take into account if the store and central server have different versions. Returns false in
+ * other cases, for example if the ignore version differences preference is set.
*/
public boolean doVersionCheck() {
if (doResetCachedInformation || ignoreVersionCheck == null) {
@@ -253,8 +247,7 @@
}
/**
- * Creates the entries in the modules by server table. Only does this if the version of the
- * modules changed.
+ * Creates the entries in the modules by server table. Only does this if the version of the modules changed.
*/
public void recomputeCurrentServerVersions() {
// read the modules and add the version
@@ -523,8 +516,7 @@
}
/**
- * Return true if the store and central versions are the same or if no version differences should
- * be checked.
+ * Return true if the store and central versions are the same or if no version differences should be checked.
*
* @return
*/
diff --git a/src/org/openbravo/retail/storeserver/synchronization/StoreSynchronizationComponentProvider.java b/src/org/openbravo/retail/storeserver/synchronization/StoreSynchronizationComponentProvider.java
--- a/src/org/openbravo/retail/storeserver/synchronization/StoreSynchronizationComponentProvider.java
+++ b/src/org/openbravo/retail/storeserver/synchronization/StoreSynchronizationComponentProvider.java
@@ -1,7 +1,7 @@
/*
*************************************************************************
* Openbravo DB Synchronization module for Retail
- * Copyright (C) 2016 Openbravo SLU
+ * Copyright (C) 2016-2018 Openbravo SLU
*
* The content of this file is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -56,11 +56,11 @@
globalResources.add(createComponentResource(ComponentResourceType.Static,
"web/org.openbravo.retail.storeserver.synchronization/js/serverReloadHandler.js",
POSUtils.APP_NAME));
-
+
globalResources.add(createComponentResource(ComponentResourceType.Static,
"web/org.openbravo.retail.storeserver.synchronization/js/responseCallbackHandler.js",
POSUtils.APP_NAME));
-
+
globalResources.add(createComponentResource(ComponentResourceType.Static,
"web/org.openbravo.retail.storeserver.synchronization/js/incompatibleVersionHandler.js",
POSUtils.APP_NAME));
diff --git a/src/org/openbravo/retail/storeserver/synchronization/SyncStatusOnlineTransitionHandler.java b/src/org/openbravo/retail/storeserver/synchronization/SyncStatusOnlineTransitionHandler.java
--- a/src/org/openbravo/retail/storeserver/synchronization/SyncStatusOnlineTransitionHandler.java
+++ b/src/org/openbravo/retail/storeserver/synchronization/SyncStatusOnlineTransitionHandler.java
@@ -1,7 +1,7 @@
/*
*************************************************************************
* Openbravo DB Synchronization module for Retail
- * Copyright (C) 2016-2017 Openbravo SLU
+ * Copyright (C) 2016-2018 Openbravo SLU
*
* The content of this file is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,17 +20,20 @@
package org.openbravo.retail.storeserver.synchronization;
+import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
+import org.codehaus.jettison.json.JSONObject;
import org.jumpmind.symmetric.web.ServerSymmetricEngine;
import org.openbravo.base.exception.OBException;
import org.openbravo.mobile.core.servercontroller.MobileServerController;
+import org.openbravo.mobile.core.servercontroller.MobileServerRequestExecutor;
import org.openbravo.mobile.core.servercontroller.MobileServerTransitionToOnlineHandler;
+import org.openbravo.mobile.core.servercontroller.MobileServerUtils;
import org.openbravo.replication.symmetricds.SynchronizationEngineProvider;
/**
- * This class checks if there are is any data pending to be synced from store to central or vice
- * versa. Also it checks if there are import entries to be processed. If so then the store needs to
- * wait with going online.
+ * This class checks if there are is any data pending to be synced from store to central or vice versa. Also it checks if there
+ * are import entries to be processed. If so then the store needs to wait with going online.
*
* @see RetrieveSyncStatus
* @author mtaal
@@ -76,11 +79,43 @@
.countWaitingBatchesAndImportEntries(null);
}
+ // nothing on our side
if (countWaitingEntriesAndBatches == 0) {
- goOnline = true;
+ // now call the central server to check the status of things to be sent
+ // to the store server
+ final JSONObject parameters = new JSONObject();
+ parameters.put("serverKey", MobileServerController.getInstance().getThisServerDefinition()
+ .getMobileServerKey());
+ try {
+ final JSONObject result = MobileServerRequestExecutor.getInstance()
+ .executeCentralRequest(
+ MobileServerUtils.OBWSPATH + RetrieveSyncStatus.class.getName(), parameters);
+ if (result == null) {
+ // didn't get a valid reply from the server
+ // very basic webservice, if it fails server must be offline
+ goOnline = false;
+ } else if (result.has("batchToSyncCount")) {
+ goOnline = 0 == result.getInt("batchToSyncCount");
+ if (!goOnline) {
+ offLineLog = this.getClass().getSimpleName() + " the central server has "
+ + result.getInt("batchToSyncCount")
+ + " waiting importentries/synchronization-batches for this server ";
+ }
+ } else {
+ // incorrect json, report error but still go online
+ log.error("Incorrect json format, no batchToSyncCount: " + result);
+ goOnline = true;
+ }
+ } catch (Throwable t) {
+ // remain false
+ log.error(t.getMessage(), t);
+ return;
+ }
} else {
offLineLog = this.getClass().getSimpleName() + " this server has "
+ countWaitingEntriesAndBatches + " waiting importentries/synchronization-batches ";
+ }
+ if (!goOnline && !StringUtils.isBlank(offLineLog)) {
log.warn("Not going online because: " + offLineLog);
}
} catch (Throwable t) {
@@ -98,4 +133,4 @@
return goOnline;
}
-}
+}
\ No newline at end of file
diff --git a/src/org/openbravo/retail/storeserver/synchronization/eventhandler/MobileServerEventHandler.java b/src/org/openbravo/retail/storeserver/synchronization/eventhandler/MobileServerEventHandler.java
--- a/src/org/openbravo/retail/storeserver/synchronization/eventhandler/MobileServerEventHandler.java
+++ b/src/org/openbravo/retail/storeserver/synchronization/eventhandler/MobileServerEventHandler.java
@@ -1,7 +1,7 @@
/*
*************************************************************************
* Openbravo DB Synchronization module for Retail
- * Copyright (C) 2017 Openbravo SLU
+ * Copyright (C) 2017-2018 Openbravo SLU
*
* The content of this file is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -73,7 +73,7 @@
throw new OBException("This method can only be called in multi-server-mode");
}
- final String strSql = "select 1 from sym_incoming_error";
+ final String strSql = "select 1 from sym_incoming_error where batch_id in (select batch_id from sym_incoming_batch where status = 'ER')";
// use a separate/new dal connection to prevent infinite loops in hibernate
ConnectionProvider readOnlyCP = DalConnectionProvider.getReadOnlyConnectionProvider();
Connection conn = null;
@@ -101,7 +101,8 @@
if (st != null) {
try {
st.close();
- } catch (Throwable ignore) {}
+ } catch (Throwable ignore) {
+ }
}
readOnlyCP.releaseCommitConnection(conn);
} catch (Exception e) {
@@ -139,7 +140,7 @@
}
}
}
-
+
private void updateOfflineIncomingErrorsFlag(EntityUpdateEvent event) {
final String currentState = (String) event.getCurrentState(STATUS_PROPERTY);
final String previousState = (String) event.getPreviousState(STATUS_PROPERTY);
@@ -147,10 +148,10 @@
final boolean currentStateOffline = MobileServerState.OFFLINE.getValue().equals(currentState);
final boolean previousStateOffline = MobileServerState.OFFLINE.getValue().equals(previousState);
final boolean currentStateOnline = MobileServerState.ONLINE.getValue().equals(currentState);
-
+ final Boolean offlineError = (Boolean) event.getCurrentState(OFFLINE_ERROR_PROPERTY);
if (currentStateOffline && !previousStateOffline) {
event.setCurrentState(OFFLINE_ERROR_PROPERTY, doIncomingSyncErrorsExist());
- } else if (currentStateOnline) {
+ } else if (currentStateOnline && offlineError != null && offlineError) {
event.setCurrentState(OFFLINE_ERROR_PROPERTY, false);
}
}
38036-replication-5.diff [^] (622 bytes) 2018-03-13 12:27 [Show Content] [Hide Content]diff --git a/src/org/openbravo/replication/symmetricds/diagnosis/RemoteStoreServerDiagnosisProcess.java b/src/org/openbravo/replication/symmetricds/diagnosis/RemoteStoreServerDiagnosisProcess.java
--- a/src/org/openbravo/replication/symmetricds/diagnosis/RemoteStoreServerDiagnosisProcess.java
+++ b/src/org/openbravo/replication/symmetricds/diagnosis/RemoteStoreServerDiagnosisProcess.java
@@ -51,10 +51,4 @@
}
return response;
}
-
- @Override
- // this process should be executed even if the store server state is transitioning
- protected boolean ignoreTransitioningStatus() {
- return true;
- }
}
38036-mobile-core-5.diff [^] (36,994 bytes) 2018-03-13 12:27 [Show Content] [Hide Content]diff --git a/src-db/database/sourcedata/AD_COLUMN.xml b/src-db/database/sourcedata/AD_COLUMN.xml
--- a/src-db/database/sourcedata/AD_COLUMN.xml
+++ b/src-db/database/sourcedata/AD_COLUMN.xml
@@ -800,6 +800,8 @@
<!--4FFE3405421B4551BE5C663AF9B52457--> <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
<!--4FFE3405421B4551BE5C663AF9B52457--> <ISACTIVE><![CDATA[Y]]></ISACTIVE>
<!--4FFE3405421B4551BE5C663AF9B52457--> <NAME><![CDATA[Offline_Incoming_Errors]]></NAME>
+<!--4FFE3405421B4551BE5C663AF9B52457--> <DESCRIPTION><![CDATA[Keeps track if there were incoming errors when the server goes offline.]]></DESCRIPTION>
+<!--4FFE3405421B4551BE5C663AF9B52457--> <HELP><![CDATA[Keeps track if there were incoming errors when the server goes offline. Is set to true when the server goes offline and there are incoming errors, is set to false in other cases.]]></HELP>
<!--4FFE3405421B4551BE5C663AF9B52457--> <COLUMNNAME><![CDATA[Offline_Incoming_Errors]]></COLUMNNAME>
<!--4FFE3405421B4551BE5C663AF9B52457--> <AD_TABLE_ID><![CDATA[9A030632C0FC4C4AA8A58EC59BE2D116]]></AD_TABLE_ID>
<!--4FFE3405421B4551BE5C663AF9B52457--> <AD_REFERENCE_ID><![CDATA[20]]></AD_REFERENCE_ID>
diff --git a/src-db/database/sourcedata/AD_ELEMENT.xml b/src-db/database/sourcedata/AD_ELEMENT.xml
--- a/src-db/database/sourcedata/AD_ELEMENT.xml
+++ b/src-db/database/sourcedata/AD_ELEMENT.xml
@@ -293,6 +293,9 @@
<!--C9BCAD956E664DC3B30BB5E722E7C5B1--> <COLUMNNAME><![CDATA[Offline_Incoming_Errors]]></COLUMNNAME>
<!--C9BCAD956E664DC3B30BB5E722E7C5B1--> <NAME><![CDATA[Offline_Incoming_Errors]]></NAME>
<!--C9BCAD956E664DC3B30BB5E722E7C5B1--> <PRINTNAME><![CDATA[Offline_Incoming_Errors]]></PRINTNAME>
+<!--C9BCAD956E664DC3B30BB5E722E7C5B1--> <DESCRIPTION><![CDATA[Keeps track if there were incoming errors when the server goes offline.]]></DESCRIPTION>
+<!--C9BCAD956E664DC3B30BB5E722E7C5B1--> <HELP><![CDATA[Keeps track if there were incoming errors when the server goes offline. Is set to true when the server goes offline and there are incoming errors, is set to false in other cases.]]></HELP>
+<!--C9BCAD956E664DC3B30BB5E722E7C5B1--> <PO_HELP><![CDATA[Keeps track if there were incoming errors when the server goes offline.]]></PO_HELP>
<!--C9BCAD956E664DC3B30BB5E722E7C5B1--> <AD_MODULE_ID><![CDATA[08943B85ADF64E708797A753E5B6AAEE]]></AD_MODULE_ID>
<!--C9BCAD956E664DC3B30BB5E722E7C5B1--> <ISGLOSSARY><![CDATA[N]]></ISGLOSSARY>
<!--C9BCAD956E664DC3B30BB5E722E7C5B1--></AD_ELEMENT>
diff --git a/src/org/openbravo/mobile/core/process/JSONProcessSimple.java b/src/org/openbravo/mobile/core/process/JSONProcessSimple.java
--- a/src/org/openbravo/mobile/core/process/JSONProcessSimple.java
+++ b/src/org/openbravo/mobile/core/process/JSONProcessSimple.java
@@ -22,8 +22,6 @@
import org.openbravo.dal.core.OBContext;
import org.openbravo.mobile.core.MobileCoreKernelUtils;
import org.openbravo.mobile.core.MobileStaticResourceComponent;
-import org.openbravo.mobile.core.servercontroller.MobileServerController;
-import org.openbravo.mobile.core.servercontroller.MobileServerUtils;
public abstract class JSONProcessSimple extends SecuredJSONProcess {
@@ -44,19 +42,6 @@
public void exec(Writer w, JSONObject jsonsent) throws IOException, ServletException {
- // don't do any actions when transitioning
- if (MobileServerUtils.isMultiServerEnabled()) {
- // if the request has server status info then make use of it to update the
- // server status
- MobileServerUtils.updateServerStatusFromJSON(jsonsent);
-
- if (!ignoreTransitioningStatus()
- && MobileServerController.getInstance().serverHasTransitioningStatus()) {
- MobileServerController.getInstance().writeServerStatusJSON(w);
- return;
- }
- }
-
try {
String s = exec(jsonsent).toString();
if (s.startsWith("{") && s.endsWith("}")) {
@@ -104,8 +89,7 @@
}
/**
- * Return true if the logic of the subclass should be executed also in case of transitioning
- * status. Default is false, so in case of transitioning status nothing is executed.
+ * @deprecated this method is not being used anymore
*/
protected boolean ignoreTransitioningStatus() {
return false;
diff --git a/src/org/openbravo/mobile/core/process/MobileService.java b/src/org/openbravo/mobile/core/process/MobileService.java
--- a/src/org/openbravo/mobile/core/process/MobileService.java
+++ b/src/org/openbravo/mobile/core/process/MobileService.java
@@ -50,7 +50,7 @@
@Inject
@Any
- private Instance<MobileServiceRequestAllowedHandler> allowHandlers;
+ private Instance<MobileServiceRequestHandler> requestHandlers;
public void init(ServletConfig config) {
super.init(config);
@@ -107,10 +107,10 @@
// Note: the call to the MobileServiceRequestAllowedHandler must be done
// before the content of the request is retrieved as some MobileServiceRequestAllowedHandler
// may also read the content to process the request independently
- for (Iterator<MobileServiceRequestAllowedHandler> procIter = allowHandlers.iterator(); procIter
+ for (Iterator<MobileServiceRequestHandler> procIter = requestHandlers.iterator(); procIter
.hasNext();) {
- MobileServiceRequestAllowedHandler allowHandler = procIter.next();
- if (!allowHandler.allowRequest(request, response)) {
+ MobileServiceRequestHandler handler = procIter.next();
+ if (handler.requestHandled(request, response)) {
return;
}
}
@@ -289,16 +289,34 @@
}
/**
- * Is used to control/check if a request is allowed to be handled and if not generates a response
- * to send back to the client.
+ * Is used to control/check if a request is allowed to be handled and if not generates a response to send back to the client.
+ *
+ * @deprecated use MobileServiceRequestHandler
+ * @author mtaal
+ */
+ public static abstract class MobileServiceRequestAllowedHandler extends
+ MobileServiceRequestHandler {
+ /**
+ * Return false if the request is not allowed to be processed further. In this case the callee can generate a response in the
+ * response object.
+ */
+ public abstract boolean allowRequest(HttpServletRequest request, HttpServletResponse response);
+
+ public boolean requestHandled(HttpServletRequest request, HttpServletResponse response) {
+ return !allowRequest(request, response);
+ }
+ }
+
+ /**
+ * Allows extra code to catch a request and handle it instead of the MobileService class.
*
* @author mtaal
*/
- public static abstract class MobileServiceRequestAllowedHandler {
+ public static abstract class MobileServiceRequestHandler {
/**
- * Return false if the request is not allowed to be processed further. In this case the callee
- * can generate a response in the response object.
+ * Return true if the request is handled by the handler so not be further processed by the MobileService class. Return false
+ * if the mobile service class should handle the request.
*/
- public abstract boolean allowRequest(HttpServletRequest request, HttpServletResponse response);
+ public abstract boolean requestHandled(HttpServletRequest request, HttpServletResponse response);
}
}
diff --git a/src/org/openbravo/mobile/core/servercontroller/MobileServerRequestExecutor.java b/src/org/openbravo/mobile/core/servercontroller/MobileServerRequestExecutor.java
--- a/src/org/openbravo/mobile/core/servercontroller/MobileServerRequestExecutor.java
+++ b/src/org/openbravo/mobile/core/servercontroller/MobileServerRequestExecutor.java
@@ -1,6 +1,6 @@
/*
************************************************************************************
- * Copyright (C) 2015-2016 Openbravo S.L.U.
+ * Copyright (C) 2015-2018 Openbravo S.L.U.
* Licensed under the Openbravo Commercial License version 1.0
* You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
* or in the legal folder of this module distribution.
@@ -101,7 +101,7 @@
if (MobileServerUtils.isOpenbravoServer(server)) {
wsPart = wsPart
+ (authenticationParams == null ? "" : (serviceName.contains("?") ? "&" : "?")
- + authenticationParams);
+ + authenticationParams);
if (MobileServerController.getInstance().isThisAStoreServer()) {
wsPart += "&" + SOURCE_PROP + "=" + SOURCE_STORE;
} else {
@@ -178,7 +178,7 @@
JSONObject parameters) {
int tries = 0;
boolean readTimeoutOccurred = false;
-
+
JSONObject resp = new JSONObject();
while (tries <= getMaxRetries()) {
readTimeoutOccurred = false;
@@ -191,7 +191,8 @@
}
tries++;
final String result = request(server, serviceName,
- MobileServerUtils.getAuthenticationQueryParams(), parameters == null ? "GET" : "POST", parameters);
+ MobileServerUtils.getAuthenticationQueryParams(), parameters == null ? "GET" : "POST",
+ parameters);
resp = new JSONObject(result).getJSONObject("response");
if (resp.has("serverStatus")) {
final String respStatus = resp.getString("serverStatus");
@@ -217,7 +218,7 @@
readTimeoutOccurred = "Read timed out".equals(t.getMessage());
log.error("Trying connection to " + server.getMobileServerKey() + " " + serviceName
+ " json: " + parameters, t);
-
+
}
}
if (!readTimeoutOccurred || doesReadTimeoutForceOffline()) {
@@ -413,9 +414,9 @@
return;
}
-
if (MobileServerController.getInstance().isThisAStoreServer()) {
- final boolean notOnline = !MobileServerController.getInstance().getThisMobileServerState().equals(MobileServerState.ONLINE);
+ final boolean notOnline = !MobileServerController.getInstance().getThisMobileServerState()
+ .equals(MobileServerState.ONLINE);
if (notOnline) {
// if offline-->online, then trigger an online transition
MobileServerController.getInstance().transitionToOnline();
diff --git a/src/org/openbravo/mobile/core/servercontroller/MultiServerJSONProcess.java b/src/org/openbravo/mobile/core/servercontroller/MultiServerJSONProcess.java
--- a/src/org/openbravo/mobile/core/servercontroller/MultiServerJSONProcess.java
+++ b/src/org/openbravo/mobile/core/servercontroller/MultiServerJSONProcess.java
@@ -1,6 +1,6 @@
/*
************************************************************************************
- * Copyright (C) 2016 Openbravo S.L.U.
+ * Copyright (C) 2016-2018 Openbravo S.L.U.
* Licensed under the Openbravo Commercial License version 1.0
* You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
* or in the legal folder of this module distribution.
@@ -25,13 +25,11 @@
import org.openbravo.base.provider.OBProvider;
import org.openbravo.base.util.Check;
import org.openbravo.base.weld.WeldUtils;
-import org.openbravo.client.kernel.RequestContext;
import org.openbravo.dal.core.OBContext;
import org.openbravo.dal.core.SessionHandler;
import org.openbravo.dal.service.OBDal;
import org.openbravo.erpCommon.utility.OBMessageUtils;
import org.openbravo.erpCommon.utility.SequenceIdData;
-import org.openbravo.mobile.core.MobileServerDefinition;
import org.openbravo.mobile.core.process.JSONProcessSimple;
import org.openbravo.mobile.core.process.JSONRowConverter;
import org.openbravo.mobile.core.utils.OBMOBCUtils;
@@ -46,54 +44,12 @@
import org.openbravo.service.json.JsonConstants;
/**
- * Handles many cases of WebPOS working together with central and store server. This class can
- * handle situations of a store being offline, central being offline or both being available.
- *
- * If the json is sent from WebPOS and processed on the store server there are several options which
- * play a role:
- * <ul>
- * <li>_onlyDoCentralFromStore: if this json property has value true then the action is forwarded to
- * the central. If the central server is not available then an exception is returned.</li>
- * <li>_tryCentralFromStore: if this json property has true then first the central server is tried
- * before possibly executing locally. If the central server is not available then the action is
- * executed locally and no exception is thrown. If the central server is available and the action is
- * executed there then depending on the value of the _executeInOneServer property the action is
- * repeated on the store server:
- * <ul>
- * <li>true: the action is only executed on one server. So if the central server already executed
- * the action then it is not repeated on the store server.</li>
- * <li>false: the action is executed on both servers if possible. So if the central server already
- * executed the action then it is repeated on the store server by creating an import entry.</li>
- * </ul>
- * </li>
- * </ul>
+ * Supports creating import entries to easily replicate an action to another server. Also uses the import entry archive table to
+ * check for and handle duplicate requests. Errors are stored in import entries if needed.
*
- * If the json is sent from WebPOS and processed on the central server. Happens when WebPOS connects
- * to the central server because the store server is down. Then the logic will process locally in
- * central and create an import entry which is later replicated to the store server.
- *
- * If the json is sent from the STORE in a webrequest then this is a direct call from the store
- * server, process in central but don't create import entry as the store already knows about the
- * action.
- *
- * If the json is sent from the STORE to central not-in-a-webrequest then this is an import entry
- * replicated from the store. Set the import entry to processed after processing in central.
+ * Also supports pre and post processing actions/hooks.
*
- * If the json is sent from CENTRAL and processed in the store. Then this must be through an import
- * entry replicated from central. Process the json and set the import entry to processed.
- *
- * The source of the sending of the json is obtained from the json itself.
- *
- * Note, additional features: if the _executeInOneServer property is passed in the json then an
- * action is executed at most in one server, first central and if central is not available then in
- * the store. No import entries are created to be replicated, the assumption is that the
- * transactional tables are replicated.
- *
- * This class also provides several protected methods which can be overridden to change the generic
- * behavior in the specific concrete subclass.
- *
- * For more information see this wiki page:
- * http://wiki.openbravo.com/wiki/Retail:Store_Server#Synchronized_Transactions
+ * For more information see this wiki page: http://wiki.openbravo.com/wiki/Retail:Store_Server#Synchronized_Transactions
*
* @author mtaal
*/
@@ -110,7 +66,7 @@
/**
* @deprecated use {@link MobileServerRequestExecutor#SOURCE_WEBPOS}
*/
- public static final String SOURCE_WEBPOS = MobileServerRequestExecutor.SOURCE_WEBPOS;
+ public static final String SOURCE_WEBPOS = MobileServerRequestExecutor.SOURCE_WEBPOS;
/**
* @deprecated use {@link MobileServerRequestExecutor#SOURCE_STORE}
*/
@@ -194,122 +150,51 @@
executeProcessHooks(jsonSent);
String messageId = null;
try {
- try {
- // handle different cases
- if (!jsonSent.has(MobileServerRequestExecutor.SOURCE_PROP)) {
- jsonSent.put(MobileServerRequestExecutor.SOURCE_PROP, MobileServerRequestExecutor.SOURCE_WEBPOS);
- }
+ // make sure the json has a message id so duplicates can be detected
+ if (!jsonSent.has("messageId")) {
+ jsonSent.put("messageId", SequenceIdData.getUUID());
+ }
+ messageId = jsonSent.getString("messageId");
- // make sure the json has a message id so duplicates can be detected
- if (!jsonSent.has("messageId")) {
- jsonSent.put("messageId", SequenceIdData.getUUID());
- }
- messageId = jsonSent.getString("messageId");
+ // check if allowed to execute, if this is a store server
+ if (MobileServerController.getInstance().isThisAStoreServer()
+ && executeOnlyInCentral(jsonSent)) {
+ returnResult = OBMOBCUtils.createSimpleErrorJson("OBMOBC_MsgCentralServerNotAvailable");
+ } else {
+ // execute the action
+ returnResult = doExecute(jsonSent);
+ }
- final String source = jsonSent.getString(SOURCE_PROP);
+ if (log.isDebugEnabled()) {
+ log.debug("Result (" + logTime + "): " + returnResult);
+ }
- if (SOURCE_CENTRAL.equals(source)) {
- // case 1: processing an import entry in the store which was processed before in the
- // central server
- returnResult = executeLocal(jsonSent);
+ // last checks, return is done at the end of the method
+ Check.isNotNull(returnResult, "Return result may not be null");
+ errorOccurred = isErrorJson(returnResult);
- if (getImportEntryId() == null) {
- // note: normal case is that we are processed from import entry
- // anything else is not expected
- // in future it can be the case that also central sends transactions
- // directly to store using a webservice, at that time this line may go
- throw new OBException("Source central is expected to go through import entry "
- + jsonSent);
+ // set correct import entry status
+ if (!errorOccurred) {
+ OBContext.setAdminMode();
+ try {
+ if (getImportEntryId() != null
+ && !importEntryManager.isImportEntryError(getImportEntryId())) {
+ importEntryManager.setImportEntryProcessed(getImportEntryId());
}
- } else if (SOURCE_WEBPOS.equals(source)) {
- if (MobileServerController.getInstance().isThisAStoreServer()) {
- // case 2: if from webpos and this is store server
- returnResult = executeFromWebPOSInStore(jsonSent);
- } else if (MobileServerController.getInstance().isThisACentralServer()) {
- // case 3: if from webpos and this is central server then we are called directly
- // from webpos, happens when store server is down,
- // the import entry should be created to synchronize
- // back to the store server
- returnResult = executeFromWebPOSInCentral(jsonSent);
- } else {
- // case 4 not a multi-server environment, process locally
- returnResult = executeLocal(jsonSent);
+ if (getImportEntryId() == null) {
+ updateArchiveStatus(messageId, "Processed");
}
- } else if (SOURCE_STORE.equals(source)) {
- // case 5: transaction received from store, we must be central then
- if (MobileServerController.getInstance().isThisACentralServer()) {
-
- // execute locally
- returnResult = executeLocal(jsonSent);
-
- if (isErrorJson(returnResult)) {
- // don't do anything, will be handled in finally block
- } else if (RequestContext.get().getRequest() != null) {
- // case 5a: web request send from store, don't create import entry as this
- // is done by store itself, only create archive
- // be defensive
- if (getImportEntryId() != null) {
- throw new OBException("Illegal flow, did not expect import entry to be set "
- + jsonSent);
- }
-
- } else {
- // case 5b: import entry received from store server, this flow happens
- // when the store server can not reach central and processes transactions
- // offline/in the store
-
- // be defensive
- if (getImportEntryId() == null) {
- throw new OBException("Illegal flow, expect import entry to be set " + jsonSent);
- }
-
- // import entry is set to processed in finally block
- }
- } else {
- // defensive, not expected flow
- throw new OBException("Source of json is STORE but this is "
- + "not a central server unsupported case " + jsonSent);
- }
- } else {
- // defensive coding
- throw new OBException("Source not supported, see json " + jsonSent);
+ OBDal.getInstance().commitAndClose();
+ } finally {
+ OBContext.restorePreviousMode();
}
- if (log.isDebugEnabled()) {
- log.debug("Result (" + logTime + "): " + returnResult);
- }
-
- // last checks, return is done at the end of the method
- Check.isNotNull(returnResult, "Return result may not be null");
- errorOccurred = isErrorJson(returnResult);
- } finally {
+ // kick the import entry thread to process right away
+ importEntryManager.notifyNewImportEntryCreated();
+ }
- // note this finally block is inside another finally block
- // because the commit here can again throw an exception
- // which should be correctly handled.
- if (!errorOccurred) {
- OBContext.setAdminMode();
- try {
- if (getImportEntryId() != null
- && !importEntryManager.isImportEntryError(getImportEntryId())) {
- importEntryManager.setImportEntryProcessed(getImportEntryId());
- }
-
- if (getImportEntryId() == null) {
- updateArchiveStatus(messageId, "Processed");
- }
-
- OBDal.getInstance().commitAndClose();
- } finally {
- OBContext.restorePreviousMode();
- }
-
- // kick the import entry thread to process right away
- importEntryManager.notifyNewImportEntryCreated();
- }
- }
} catch (Throwable t) {
thrownError = t;
log.error(t.getMessage() + " - " + (jsonSent != null ? jsonSent.toString() : "NULL"), t);
@@ -385,237 +270,69 @@
/**
* This method should do the real action, and return the json response.
*
- * Any error situation should be handled by throwing an exception. This exception is handled in
- * this class and returned to the caller of this class.
+ * Any error situation should be handled by throwing an exception. This exception is handled in this class and returned to the
+ * caller of this class.
*/
protected abstract JSONObject execute(JSONObject json);
- protected JSONObject executeFromWebPOSInCentral(JSONObject jsonSent) throws Exception {
- // case 2: if from webpos and central server then we are called directly
- // from webpos, the processed import entry should be created to synchronize
- // back to the store server
+ private JSONObject doExecute(JSONObject jsonSent) throws Exception {
+
final JSONObject result = executeLocal(jsonSent);
if (!isErrorJson(result) && !executeInOneServer(jsonSent)) {
- final JSONObject json = new JSONObject(jsonSent.toString());
- // sent along from the central to store, set the source to CENTRAL
- json.put(MobileServerRequestExecutor.SOURCE_PROP, MobileServerRequestExecutor.SOURCE_CENTRAL);
- createImportEntry(jsonSent.getString("messageId"), json, result, null);
+ createImportEntry(jsonSent.getString("messageId"), jsonSent, result, null);
// is set to processed to in finally block of main loop
}
-
- // return the result to the store server
return result;
}
- protected JSONObject executeFromWebPOSInStore(JSONObject jsonSent) throws Exception {
- final String messageId = jsonSent.getString("messageId");
-
- // if only execute in central then forward to central, note if central is offline
- // then an exception is thrown but no transition is happening
- if (executeOnlyInCentral(jsonSent)) {
- final JSONObject jsonToCentral = new JSONObject(jsonSent.toString());
- // sent along from the store to central, set the source to STORE
- jsonToCentral.put(MobileServerRequestExecutor.SOURCE_PROP, MobileServerRequestExecutor.SOURCE_STORE);
- // prevent cycling around
- jsonToCentral.remove(CALL_ONLY_CENTRAL_PROP);
- JSONObject centralResult = null;
- try {
- centralResult = MobileServerRequestExecutor.getInstance().executeCentralRequest(
- MobileServerUtils.OBWSPATH + this.getClass().getName(), jsonToCentral);
- } catch (Throwable t) {
- return handleCentralServerRequestException(t);
- }
- afterReturnFromCentral(jsonToCentral, centralResult);
- return centralResult;
- } else
- // If store is online and central is online execute on central and create import entry to
- // process
- // locally. So in this flow the json results in processing in both central and store.
- // Unless the executeInOneServer returns true then it is processed in one server
- // only
- // The store server processing is done in parallel by creating an import entry.
- // In this execution flow transactional tables are not replicated. The import entry is
- // potentially replicated. This all depends on the synchronized table setup.
- if (MobileServerController.getInstance().getThisMobileServerState()
- .equals(MobileServerState.ONLINE)
- && executeFirstInCentral(jsonSent)
- && MobileServerController.getInstance().isCentralServerOnline()) {
- try {
- JSONObject centralResult = null;
- // execute in the central server
- final JSONObject jsonToCentral = new JSONObject(jsonSent.toString());
- try {
- // sent along from the store to central, set the source to STORE
- jsonToCentral.put(SOURCE_PROP, SOURCE_STORE);
- // prevent cycling around
- jsonToCentral.remove(CALL_CENTRAL_PROP);
- centralResult = MobileServerRequestExecutor.getInstance().executeCentralRequest(
- MobileServerUtils.OBWSPATH + this.getClass().getName(), jsonToCentral);
- } catch (Exception e) {
- return handleCentralServerRequestException(e);
- }
- // do after the catch block, so that a failure here does not force the system
- // to go offline
- afterReturnFromCentral(jsonToCentral, centralResult);
-
- // central server is offline, check if transitioning
- if (centralResult.has("serverStatus")
- && !centralResult.get("serverStatus").equals(MobileServerState.ONLINE.getValue())) {
-
- // if transitioning then don't do anything local anymore, return.
- final MobileServerDefinition server = MobileServerController.getInstance()
- .getThisServerDefinition();
- if (MobileServerState.TRANSITION_TO_ONLINE.getValue().equals(server.getStatus())
- || MobileServerState.TRANSITION_TO_OFFLINE.getValue().equals(server.getStatus())) {
- final JSONObject result = new JSONObject();
- result.put("serverStatusSignal", server.getStatus());
- return result;
- } else if (MobileServerState.OFFLINE.getValue().equals(server.getStatus())) {
- // went offline along the way, execute local
- final JSONObject result = executeLocal(jsonSent);
- if (isErrorJson(result)) {
- return result;
- }
- if (!executeInOneServer(jsonSent)) {
- createImportEntry(messageId, jsonSent, result, null);
- // processed is set in finally block of main loop
- }
+ protected JSONObject executeLocal(JSONObject jsonSent) throws Exception {
- return result;
- }
- }
-
- // error in central, return the error and don't create local import entry
- if (isErrorJson(centralResult)) {
- return centralResult;
- }
-
- // a webrequest, create local copy for local processing
- if (getImportEntryId() == null && !executeInOneServer(jsonSent)) {
- // local copy
- final JSONObject json = new JSONObject(jsonSent.toString());
- // set the source to central has it already was processed there, so
- // is the same as if the central sends it back to store
- // this property is not overwritten in createImportEntry
- json.put(SOURCE_PROP, SOURCE_CENTRAL);
-
- // create local import entry which will be processed in parallel
- // calls setImportEntryId
- createImportEntry(messageId, json, centralResult, null);
- // this is a special case, the created import entry should not be set to
- // processed. This is accomplished by resetting the global import entry id to
- // null. The createImportEntry will set it, so here we reset it.
- setImportEntryId(null);
- }
+ final JSONObject result = execute(jsonSent);
- return centralResult;
- } catch (Throwable t) {
- throw new OBException(t);
- }
- } else if (MobileServerController.getInstance().serverHasTransitioningStatus()) {
- final JSONObject result = new JSONObject();
- MobileServerController.getInstance().setServerStatusJSON(result);
- return result;
- } else {
- // store offline, execute local and if needed create processed import entry which will be
- // replicated to the central server
- final JSONObject result = executeLocal(jsonSent);
- if (isErrorJson(result)) {
- return result;
- }
- if (!executeInOneServer(jsonSent)) {
- // import entry will be replicated to central to be executed there
- createImportEntry(messageId, jsonSent, result, null);
- // processed is set in finally block of main loop
- }
-
- return result;
- }
- }
-
- private JSONObject handleCentralServerRequestException(Throwable t) throws Exception {
- log.error(t.getMessage(), t);
-
- OBContext.setAdminMode(false);
- try {
- // set the central server as not being reachable
- final MobileServerDefinition centralServer = MobileServerController.getInstance()
- .getCentralServer();
- centralServer.setStatus(MobileServerState.OFFLINE.getValue());
- OBDal.getInstance().save(centralServer);
- } finally {
- OBContext.restorePreviousMode();
- }
-
- if (!MobileServerState.TRANSITION_TO_OFFLINE.equals(MobileServerController.getInstance()
- .getThisMobileServerState())) {
- // transition to offline,
- // which causes the next if to be executed
- log.info("Could not communicate with the central server, starting transition to offline");
- MobileServerController.getInstance().transitionToOffline();
- }
-
- if (MobileServerController.getInstance().serverHasTransitioningStatus()) {
- final JSONObject result = new JSONObject();
- MobileServerController.getInstance().setServerStatusJSON(result);
+ // error was returned here
+ if (isErrorJson(result)) {
return result;
}
- // return a exception json, the transaction will be committed is fine
- // as the central server will move to offline so database action
- // happened
- return OBMOBCUtils.createSimpleErrorJson("OBMOBC_MsgCentralServerNotAvailable");
+ return createSuccessResponse(jsonSent, result);
}
/**
- * Method which is called after the logic has called central and received a response from central.
- *
- * Is therefore only called when the current server is a store server
- *
- * @param jsonSent
- * the json which was sent to central
- * @param resultFromCentral
- * the result received back from central
- */
- protected void afterReturnFromCentral(JSONObject jsonSent, JSONObject resultFromCentral) {
- }
-
- /**
- * Controls if when the request is being handled in the store it should forward to central and not
- * do any local actions, so not create a local import entry.
+ * Controls if when the request is being handled in the store it will return an error json. Default is false.
*/
protected boolean executeOnlyInCentral(JSONObject json) throws JSONException {
return json.has(CALL_ONLY_CENTRAL_PROP) && json.getBoolean(CALL_ONLY_CENTRAL_PROP);
}
/**
- * Execute the action in one server at most, assume that any transactions are replicated through
- * other means than import entry.
+ * Execute the action in one server at most, assume that any transactions are replicated through other means than import entry.
*/
protected boolean executeInOneServer(JSONObject json) throws JSONException {
return json.has(EXECUTE_IN_ONE_SERVER) && json.getBoolean(EXECUTE_IN_ONE_SERVER);
}
/**
- * Controls if the store should first call central and then create a local import entry for local
- * transactions.
+ * Controls if the store should first call central and then create a local import entry for local transactions.
+ *
+ * This method is not used anymore.
+ *
+ * @deprecated
*/
protected boolean executeFirstInCentral(JSONObject json) throws JSONException {
+ log.warn("The executeFirstInCentral method is not used anymore");
return json.has(CALL_CENTRAL_PROP) && json.getBoolean(CALL_CENTRAL_PROP);
}
/**
* Creates the import entry by combining the result json and the json which was sent in.
*
- * Organization in which the import entry will be created can be passed in. This to allow
- * distributing the import entry to other stores.
+ * Organization in which the import entry will be created can be passed in. This to allow distributing the import entry to other
+ * stores.
*
- * If null is passed in for the organization then as a default the system will use the current
- * organization of the user.
+ * If null is passed in for the organization then as a default the system will use the current organization of the user.
*
- * Override this method and call the super implementation with a different organization if this is
- * functionally relevant.
+ * Override this method and call the super implementation with a different organization if this is functionally relevant.
*/
protected void createImportEntry(String messageId, JSONObject sentIn, JSONObject processResult,
Organization organization) throws JSONException {
@@ -630,13 +347,6 @@
setImportEntryId(messageId);
final JSONObject result = new JSONObject(sentIn.toString());
-
- // can already be set by caller
- if (!result.has(MobileServerRequestExecutor.SOURCE_PROP)) {
- result.put(MobileServerRequestExecutor.SOURCE_PROP,
- (MobileServerController.getInstance().isThisACentralServer() ? MobileServerRequestExecutor.SOURCE_CENTRAL
- : MobileServerRequestExecutor.SOURCE_STORE));
- }
result.put(RESULT_PROP, processResult);
OBContext.setAdminMode(true);
@@ -785,18 +495,6 @@
}
}
- protected JSONObject executeLocal(JSONObject jsonSent) throws Exception {
-
- final JSONObject result = execute(jsonSent);
-
- // error was returned here
- if (isErrorJson(result)) {
- return result;
- }
-
- return createSuccessResponse(jsonSent, result);
- }
-
private JSONObject createSuccessResponse(JSONObject jsonSent, JSONObject result) {
try {
final JSONObject response = new JSONObject();
diff --git a/src/org/openbravo/mobile/core/servercontroller/SynchronizedServerProcessCaller.java b/src/org/openbravo/mobile/core/servercontroller/SynchronizedServerProcessCaller.java
--- a/src/org/openbravo/mobile/core/servercontroller/SynchronizedServerProcessCaller.java
+++ b/src/org/openbravo/mobile/core/servercontroller/SynchronizedServerProcessCaller.java
@@ -29,14 +29,13 @@
import org.openbravo.service.json.JsonConstants;
/**
- * Handler which receives a json which calls other json processes in order and does one commit at
- * the end. Exceptions are returned directly to the client.
+ * Handler which receives a json which calls other json processes in order and does one commit at the end. Exceptions are returned
+ * directly to the client.
*
- * The class has a main flow logic which calls central server or processes locally depending on
- * being online or offline or being store or central server.
+ * The class has a main flow logic which calls central server or processes locally depending on being online or offline or being
+ * store or central server.
*
- * For more information see these wiki pages:
- * http://wiki.openbravo.com/wiki/Multi-Server_Process_Calls_Concept
+ * For more information see these wiki pages: http://wiki.openbravo.com/wiki/Multi-Server_Process_Calls_Concept
* http://wiki.openbravo.com/wiki/Retail:Store_Server#Synchronized_Transactions
*
* @author mtaal
38036-retail-posterminal-5.diff [^] (6,406 bytes) 2018-03-13 12:28 [Show Content] [Hide Content]diff --git a/src/org/openbravo/retail/posterminal/master/CashupSynchronized.java b/src/org/openbravo/retail/posterminal/master/CashupSynchronized.java
deleted file mode 100644
--- a/src/org/openbravo/retail/posterminal/master/CashupSynchronized.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- ************************************************************************************
- * Copyright (C) 2016 Openbravo S.L.U.
- * Licensed under the Openbravo Commercial License version 1.0
- * You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
- * or in the legal folder of this module distribution.
- ************************************************************************************
- */
-package org.openbravo.retail.posterminal.master;
-
-import javax.servlet.ServletException;
-
-import org.apache.log4j.Logger;
-import org.codehaus.jettison.json.JSONException;
-import org.codehaus.jettison.json.JSONObject;
-import org.hibernate.Query;
-import org.openbravo.base.exception.OBException;
-import org.openbravo.dal.core.SessionHandler;
-import org.openbravo.mobile.core.servercontroller.MobileServerController;
-import org.openbravo.mobile.core.servercontroller.MobileServerRequestExecutor;
-import org.openbravo.mobile.core.servercontroller.MobileServerUtils;
-import org.openbravo.mobile.core.servercontroller.SynchronizedServerProcessCaller;
-import org.openbravo.model.common.order.Order;
-import org.openbravo.retail.posterminal.OBPOSErrors;
-import org.openbravo.service.importprocess.ImportEntry;
-
-/**
- * A read cashup information class which is used in case of running in synchronized mode. First call
- * the central server to get the latest cashup information and return that if available.
- *
- * @author mtaal
- */
-public class CashupSynchronized extends Cashup {
- private static final Logger log = Logger.getLogger(CashupSynchronized.class);
-
- @Override
- public JSONObject exec(JSONObject json) throws JSONException, ServletException {
- if (MobileServerController.getInstance().isThisACentralServer()) {
- return executeLocal(json);
- } else if (MobileServerController.getInstance().isCentralServerOnline()) {
- log.debug("Central server is online, calling it to get latest cashup information");
- try {
- return MobileServerRequestExecutor.getInstance().executeCentralRequest(
- MobileServerUtils.OBWSPATH + this.getClass().getName(), json);
- } catch (Throwable t) {
- // something goes wrong on central, try local
- // should fail as there are errors in the import queue
- return executeLocal(json);
- }
- } else {
- return executeLocal(json);
- }
- }
-
- private JSONObject executeLocal(JSONObject json) throws JSONException, ServletException {
- if (isDataInQueue(json)) {
- throw new OBException(
- "Data on the server is in error/initial state, cashup information can not be retrieved");
- }
- return super.exec(json);
- }
-
- private boolean isDataInQueue(JSONObject json) throws JSONException {
- final String posId = json.getString("pos");
- {
- final Query qry = SessionHandler
- .getInstance()
- .getSession()
- .createQuery(
- "select count(*) from " + ImportEntry.ENTITY_NAME + " where ("
- + ImportEntry.PROPERTY_IMPORTSTATUS + "='Error' or "
- + ImportEntry.PROPERTY_IMPORTSTATUS + "='Initial') and "
- + ImportEntry.PROPERTY_TYPEOFDATA + "='"
- + SynchronizedServerProcessCaller.SYNCHRONIZED_DATA_TYPE + "' and "
- + ImportEntry.PROPERTY_OBPOSPOSTERMINAL + "='" + posId + "'");
- if (((Number) qry.uniqueResult()).intValue() > 0) {
- return true;
- }
- }
- {
- final Query qry = SessionHandler
- .getInstance()
- .getSession()
- .createQuery(
- "select count(*) from " + OBPOSErrors.ENTITY_NAME + " where "
- + OBPOSErrors.PROPERTY_ORDERSTATUS + "='N' and "
- + OBPOSErrors.PROPERTY_TYPEOFDATA + "='" + Order.ENTITY_NAME + "' and "
- + OBPOSErrors.PROPERTY_OBPOSAPPLICATIONS + "='" + posId + "'");
- if (((Number) qry.uniqueResult()).intValue() > 0) {
- return true;
- }
- }
- return false;
- }
-}
diff --git a/web/org.openbravo.retail.posterminal/js/utils/cashUpReportUtils.js b/web/org.openbravo.retail.posterminal/js/utils/cashUpReportUtils.js
--- a/web/org.openbravo.retail.posterminal/js/utils/cashUpReportUtils.js
+++ b/web/org.openbravo.retail.posterminal/js/utils/cashUpReportUtils.js
@@ -1,6 +1,6 @@
/*
************************************************************************************
- * Copyright (C) 2012-2017 Openbravo S.L.U.
+ * Copyright (C) 2012-2018 Openbravo S.L.U.
* Licensed under the Openbravo Commercial License version 1.0
* You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
* or in the legal folder of this module distribution.
@@ -349,9 +349,6 @@
Promise.all(promises).then(callback);
} else {
var service = 'org.openbravo.retail.posterminal.master.Cashup';
- if (OB.MobileApp.model.hasPermission('OBMOBC_SynchronizedMode', true)) {
- service = 'org.openbravo.retail.posterminal.master.CashupSynchronized';
- }
//2. Search in server
new OB.DS.Process(service).exec({
isprocessed: 'Y'
@@ -461,7 +458,6 @@
OB.UTIL.rebuildCashupFromServer = function (callback, errorCallback) {
var service = 'org.openbravo.retail.posterminal.master.Cashup';
if (OB.MobileApp.model.hasPermission('OBMOBC_SynchronizedMode', true)) {
- service = 'org.openbravo.retail.posterminal.master.CashupSynchronized';
OB.UTIL.showLoading(true);
}
new OB.DS.Process(service).exec({
@@ -538,9 +534,6 @@
if (cashUpProcessed.length === 0) {
if (!skipSearchBackend) {
var service = 'org.openbravo.retail.posterminal.master.Cashup';
- if (OB.MobileApp.model.hasPermission('OBMOBC_SynchronizedMode', true)) {
- service = 'org.openbravo.retail.posterminal.master.CashupSynchronized';
- }
// Search in the backoffice
new OB.DS.Process(service).exec({
isprocessed: 'N',
|