You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by bb...@apache.org on 2019/04/30 18:11:12 UTC
[geode-native] branch develop updated: GEODE-6624: fix nested
exception causing SIGABRT (#478)
This is an automated email from the ASF dual-hosted git repository.
bbender pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode-native.git
The following commit(s) were added to refs/heads/develop by this push:
new cc75539 GEODE-6624: fix nested exception causing SIGABRT (#478)
cc75539 is described below
commit cc75539abea0a77d1f9fa4f70db0d26b20be6bb8
Author: Blake Bender <bb...@pivotal.io>
AuthorDate: Tue Apr 30 11:11:08 2019 -0700
GEODE-6624: fix nested exception causing SIGABRT (#478)
* GEODE-6624: Fix nested exception in geode-native causing SIGABRT
- Add test case to reproduce original bug.
- Generated a function to return string constants
- Added a note to corresponding server bug
- Server team will need to change the type of exception expected in the test to repro their bug
Co-authored-by: Matthew Reddington <mr...@pivotal.io>
---
CMakeLists.txt | 2 +-
.../integration-test2/FunctionExecutionTest.cs | 25 +++++
cppcache/CMakeLists.txt | 2 +-
cppcache/integration/framework/CMakeLists.txt | 11 +-
cppcache/integration/framework/Gfsh.h | 14 +++
cppcache/integration/framework/GfshExecute.cpp | 2 +-
cppcache/integration/framework/GfshExecute.h | 2 +-
cppcache/integration/framework/TestConfig.cpp | 0
.../framework/{config.h.in => TestConfig.cpp.in} | 15 +--
.../framework/{config.h.in => TestConfig.h} | 6 +-
cppcache/integration/framework/config.h.in | 1 +
.../integration/test/FunctionExecutionTest.cpp | 65 ++++++++---
cppcache/src/TcrChunkedContext.hpp | 2 +
cppcache/src/TcrConnection.cpp | 122 +++++++++++----------
tests/javaobject/NonDeserializableObject.java | 67 +++++++++++
...Function_SendObjectWhichCantBeDeserialized.java | 66 +++++++++++
16 files changed, 313 insertions(+), 89 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b0ce016..f3dd50c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -348,6 +348,7 @@ set_target_properties(run-integration-tests PROPERTIES
find_package(OpenSSL REQUIRED)
+add_subdirectory(tests/javaobject)
add_subdirectory(dependencies)
add_subdirectory(openssl-compat)
add_subdirectory(cppcache)
@@ -357,7 +358,6 @@ add_subdirectory(sqliteimpl)
add_subdirectory(templates/security)
add_subdirectory(docs/api)
add_subdirectory(examples)
-add_subdirectory(tests/javaobject)
if (${BUILD_CLI})
add_subdirectory(clicache)
endif()
diff --git a/clicache/integration-test2/FunctionExecutionTest.cs b/clicache/integration-test2/FunctionExecutionTest.cs
index 6688d31..81b4018 100644
--- a/clicache/integration-test2/FunctionExecutionTest.cs
+++ b/clicache/integration-test2/FunctionExecutionTest.cs
@@ -132,5 +132,30 @@ namespace Apache.Geode.Client.IntegrationTests
Assert.Equal(expectedResultCount, resultList.Count);
}
}
+
+ [Fact(Skip = "Waiting for a fix from Geode server.")]
+ public void FunctionReturnsObjectWhichCantBeDeserializedOnServer()
+ {
+ using (var cluster = new Cluster(output, CreateTestCaseDirectoryName(), 1, 2))
+ {
+ Assert.True(cluster.Start());
+ Assert.Equal(0, cluster.Gfsh.create().region()
+ .withName("region")
+ .withType("REPLICATE")
+ .execute());
+ Assert.Equal(0, cluster.Gfsh.deploy()
+ .withJar(Config.JavaobjectJarPath)
+ .execute());
+
+ var cache = cluster.CreateCache();
+ var pool = cache.GetPoolFactory().AddLocator("localhost", 10334).Create("pool");
+ var region = cache.CreateRegionFactory(RegionShortcut.PROXY)
+ .SetPoolName("pool")
+ .Create<object, object>("region");
+
+ var exc = Client.FunctionService<List<object>>.OnRegion<object, object>(region);
+ Assert.Throws<FunctionExecutionException>(() => exc.Execute("executeFunction_SendObjectWhichCantBeDeserialized"));
+ }
}
+ }
}
diff --git a/cppcache/CMakeLists.txt b/cppcache/CMakeLists.txt
index fc357bb..da62541 100644
--- a/cppcache/CMakeLists.txt
+++ b/cppcache/CMakeLists.txt
@@ -132,4 +132,4 @@ add_subdirectory(integration-test)
if (BUILD_BENCHMARKS)
add_subdirectory(benchmark)
-endif()
\ No newline at end of file
+endif()
diff --git a/cppcache/integration/framework/CMakeLists.txt b/cppcache/integration/framework/CMakeLists.txt
index 8aa234c..7b4385b 100644
--- a/cppcache/integration/framework/CMakeLists.txt
+++ b/cppcache/integration/framework/CMakeLists.txt
@@ -13,19 +13,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-configure_file(config.h.in config.h)
+get_target_property(JAVAOBJECT_JAR_PATH javaobject JAR_FILE)
+
+configure_file(TestConfig.cpp.in TestConfig.cpp)
add_library(integration-framework STATIC
Gfsh.cpp
- Gfsh.h
Framework.cpp
- Framework.h
Cluster.cpp
- Cluster.h
GfshExecute.cpp
- GfshExecute.h
+ ${CMAKE_CURRENT_BINARY_DIR}/TestConfig.cpp
)
+add_dependencies(integration-framework javaobject)
+
target_compile_definitions(integration-framework
PUBLIC
BOOST_ASIO_HAS_MOVE
diff --git a/cppcache/integration/framework/Gfsh.h b/cppcache/integration/framework/Gfsh.h
index 20d9713..c03831f 100644
--- a/cppcache/integration/framework/Gfsh.h
+++ b/cppcache/integration/framework/Gfsh.h
@@ -45,6 +45,9 @@ class Gfsh {
class Shutdown;
Shutdown shutdown() { return Shutdown{*this}; }
+ class Deploy;
+ Deploy deploy() { return Deploy(*this); }
+
class Verb {
public:
protected:
@@ -252,6 +255,17 @@ class Gfsh {
};
};
+ class Deploy : public Command<void> {
+ public:
+ explicit Deploy(Gfsh &gfsh) : Command{gfsh, "deploy"} {}
+
+ Deploy &jar(const std::string &jarFile) {
+ command_ += " --jars=" + jarFile;
+
+ return *this;
+ }
+ };
+
protected:
virtual void execute(const std::string &command) = 0;
};
diff --git a/cppcache/integration/framework/GfshExecute.cpp b/cppcache/integration/framework/GfshExecute.cpp
index 5ae9023..4ea1b55 100644
--- a/cppcache/integration/framework/GfshExecute.cpp
+++ b/cppcache/integration/framework/GfshExecute.cpp
@@ -80,6 +80,6 @@ child GfshExecute::executeChild(std::vector<std::string> &commands,
// https://github.com/klemens-morgenstern/boost-process/issues/159
std::lock_guard<std::mutex> guard(g_child_mutex);
#endif
- return child(GFSH_EXECUTABLE, args = commands, env, std_out > outStream,
+ return child(getFrameworkString(FrameworkVariable::GfShExecutable), args = commands, env, std_out > outStream,
std_err > errStream);
}
diff --git a/cppcache/integration/framework/GfshExecute.h b/cppcache/integration/framework/GfshExecute.h
index 39f95e9..11922fe 100644
--- a/cppcache/integration/framework/GfshExecute.h
+++ b/cppcache/integration/framework/GfshExecute.h
@@ -34,7 +34,7 @@
w_constexprnonlitret, explctspectypename)
#include "Gfsh.h"
-#include "config.h"
+#include "TestConfig.h"
template <class _T>
bool starts_with(const _T &input, const _T &match) {
diff --git a/cppcache/integration/framework/TestConfig.cpp b/cppcache/integration/framework/TestConfig.cpp
new file mode 100644
index 0000000..e69de29
diff --git a/cppcache/integration/framework/config.h.in b/cppcache/integration/framework/TestConfig.cpp.in
similarity index 73%
copy from cppcache/integration/framework/config.h.in
copy to cppcache/integration/framework/TestConfig.cpp.in
index 935175f..567a290 100644
--- a/cppcache/integration/framework/config.h.in
+++ b/cppcache/integration/framework/TestConfig.cpp.in
@@ -15,11 +15,12 @@
* limitations under the License.
*/
-#pragma once
+#include "framework/TestConfig.h"
-#ifndef INTEGRATION_TEST_FRAMEWORK_CONFIG_H
-#define INTEGRATION_TEST_FRAMEWORK_CONFIG_H
-
-#define GFSH_EXECUTABLE "@Geode_gfsh_EXECUTABLE@"
-
-#endif // INTEGRATION_TEST_FRAMEWORK_CONFIG_H
+const char *getFrameworkString(FrameworkVariable name) {
+ switch(name) {
+ case FrameworkVariable::JavaObjectJarPath: return "@JAVAOBJECT_JAR_PATH@";
+ case FrameworkVariable::GfShExecutable: return "@Geode_gfsh_EXECUTABLE@";
+ default: return "";
+ }
+}
diff --git a/cppcache/integration/framework/config.h.in b/cppcache/integration/framework/TestConfig.h
similarity index 84%
copy from cppcache/integration/framework/config.h.in
copy to cppcache/integration/framework/TestConfig.h
index 935175f..aa4d81e 100644
--- a/cppcache/integration/framework/config.h.in
+++ b/cppcache/integration/framework/TestConfig.h
@@ -20,6 +20,8 @@
#ifndef INTEGRATION_TEST_FRAMEWORK_CONFIG_H
#define INTEGRATION_TEST_FRAMEWORK_CONFIG_H
-#define GFSH_EXECUTABLE "@Geode_gfsh_EXECUTABLE@"
+enum class FrameworkVariable {JavaObjectJarPath, GfShExecutable};
-#endif // INTEGRATION_TEST_FRAMEWORK_CONFIG_H
+const char *getFrameworkString(FrameworkVariable name);
+
+#endif // INTEGRATION_TEST_FRAMEWORK_CONFIG_H
diff --git a/cppcache/integration/framework/config.h.in b/cppcache/integration/framework/config.h.in
index 935175f..0ddbd5b 100644
--- a/cppcache/integration/framework/config.h.in
+++ b/cppcache/integration/framework/config.h.in
@@ -21,5 +21,6 @@
#define INTEGRATION_TEST_FRAMEWORK_CONFIG_H
#define GFSH_EXECUTABLE "@Geode_gfsh_EXECUTABLE@"
+#define JAVAOBJECT_JAR_PATH "@JAVAOBJECT_JAR_PATH@"
#endif // INTEGRATION_TEST_FRAMEWORK_CONFIG_H
diff --git a/cppcache/integration/test/FunctionExecutionTest.cpp b/cppcache/integration/test/FunctionExecutionTest.cpp
index 06b9e02..8640882 100644
--- a/cppcache/integration/test/FunctionExecutionTest.cpp
+++ b/cppcache/integration/test/FunctionExecutionTest.cpp
@@ -14,10 +14,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include <gtest/gtest.h>
#include <geode/Cache.hpp>
+#include <geode/CacheFactory.hpp>
+#include <geode/CacheableBuiltins.hpp>
#include <geode/ExceptionTypes.hpp>
#include <geode/FunctionService.hpp>
#include <geode/PoolManager.hpp>
@@ -26,12 +27,15 @@
#include "framework/Cluster.h"
#include "framework/Gfsh.h"
+#include "framework/TestConfig.h"
using apache::geode::client::Cache;
using apache::geode::client::Cacheable;
using apache::geode::client::CacheableVector;
+using apache::geode::client::CacheFactory;
using apache::geode::client::FunctionExecutionException;
using apache::geode::client::FunctionService;
+using apache::geode::client::NotConnectedException;
using apache::geode::client::Region;
using apache::geode::client::RegionShortcut;
using apache::geode::client::ResultCollector;
@@ -44,6 +48,19 @@ std::shared_ptr<Region> setupRegion(Cache &cache) {
return region;
}
+class TestResultCollector : public ResultCollector {
+ virtual std::shared_ptr<CacheableVector> getResult(
+ std::chrono::milliseconds) override {
+ return std::shared_ptr<CacheableVector>();
+ }
+
+ virtual void addResult(const std::shared_ptr<Cacheable> &) override {}
+
+ virtual void endResults() override {}
+
+ virtual void clearResults() override {}
+};
+
TEST(FunctionExecutionTest, UnknownFunctionOnServer) {
Cluster cluster{LocatorCount{1}, ServerCount{1}};
cluster.getGfsh()
@@ -77,19 +94,6 @@ TEST(FunctionExecutionTest, UnknownFunctionOnRegion) {
FunctionExecutionException);
}
-class TestResultCollector : public ResultCollector {
- virtual std::shared_ptr<CacheableVector> getResult(
- std::chrono::milliseconds) override {
- return std::shared_ptr<CacheableVector>();
- }
-
- virtual void addResult(const std::shared_ptr<Cacheable> &) override {}
-
- virtual void endResults() override {}
-
- virtual void clearResults() override {}
-};
-
TEST(FunctionExecutionTest, UnknownFunctionAsyncOnServer) {
Cluster cluster{LocatorCount{1}, ServerCount{1}};
cluster.getGfsh()
@@ -125,3 +129,36 @@ TEST(FunctionExecutionTest, UnknownFunctionAsyncOnRegion) {
.execute("I_Don_t_Exist"),
FunctionExecutionException);
}
+
+TEST(FunctionExecutionTest,
+ FunctionReturnsObjectWhichCantBeDeserializedOnServer) {
+ Cluster cluster{LocatorCount{1}, ServerCount{2}};
+ cluster.getGfsh()
+ .create()
+ .region()
+ .withName("region")
+ .withType("REPLICATE")
+ .execute();
+
+ cluster.getGfsh()
+ .deploy()
+ .jar(getFrameworkString(FrameworkVariable::JavaObjectJarPath))
+ .execute();
+
+ auto cache = CacheFactory().set("log-level", "none").create();
+ auto pool = cache.getPoolManager()
+ .createFactory()
+ .addLocator("localhost", 10334)
+ .create("pool");
+ auto region = cache.createRegionFactory(RegionShortcut::PROXY)
+ .setPoolName("pool")
+ .create("region");
+
+ const char *GetScopeSnapshotsFunction =
+ "executeFunction_SendObjectWhichCantBeDeserialized";
+ auto functionService = FunctionService::onRegion(region);
+ ASSERT_THROW(functionService.execute(GetScopeSnapshotsFunction),
+ NotConnectedException);
+
+ cache.close();
+}
diff --git a/cppcache/src/TcrChunkedContext.hpp b/cppcache/src/TcrChunkedContext.hpp
index e5df84c..ab8614f 100644
--- a/cppcache/src/TcrChunkedContext.hpp
+++ b/cppcache/src/TcrChunkedContext.hpp
@@ -111,6 +111,8 @@ class TcrChunkedResult {
inline void setException(std::shared_ptr<Exception> ex) { m_ex = ex; }
inline std::shared_ptr<Exception>& getException() { return m_ex; }
+
+ inline void clearException() { m_ex = nullptr; }
};
/**
diff --git a/cppcache/src/TcrConnection.cpp b/cppcache/src/TcrConnection.cpp
index b38bc25..2089580 100644
--- a/cppcache/src/TcrConnection.cpp
+++ b/cppcache/src/TcrConnection.cpp
@@ -963,77 +963,85 @@ void TcrConnection::readMessageChunked(
public:
FinalizeProcessChunk(TcrMessageReply& reply, uint16_t endpointmemId)
: m_reply(reply), m_endpointmemId(endpointmemId) {}
- ~FinalizeProcessChunk() {
+ ~FinalizeProcessChunk() noexcept(false) {
// Enqueue a nullptr chunk indicating a wait for processing to complete.
m_reply.processChunk(nullptr, 0, m_endpointmemId);
}
} endProcessChunk(reply, m_endpointObj->getDistributedMemberID());
- bool first = true;
- do {
- // uint8_t chunk_header[HDR_LEN];
- if (!first) {
- error = receiveData(reinterpret_cast<char*>(msg_header + HDR_LEN_12),
- HDR_LEN, headerTimeout, true, false);
+
+ try {
+ bool first = true;
+ do {
+ // uint8_t chunk_header[HDR_LEN];
+ if (!first) {
+ error = receiveData(reinterpret_cast<char*>(msg_header + HDR_LEN_12),
+ HDR_LEN, headerTimeout, true, false);
+ if (error != CONN_NOERR) {
+ if (error & CONN_TIMEOUT) {
+ throwException(TimeoutException(
+ "TcrConnection::readMessageChunked: "
+ "connection timed out while receiving chunk header"));
+ } else {
+ throwException(GeodeIOException(
+ "TcrConnection::readMessageChunked: "
+ "connection failure while receiving chunk header"));
+ }
+ }
+ } else {
+ first = false;
+ }
+ ++chunkNum;
+
+ LOGDEBUG(
+ "TcrConnection::readMessageChunked: received chunk header %d "
+ "from endpoint %s; bytes: %s",
+ chunkNum, m_endpoint,
+ Utils::convertBytesToString((msg_header + HDR_LEN_12), HDR_LEN)
+
+ .c_str());
+
+ auto input = m_connectionManager->getCacheImpl()->createDataInput(
+ msg_header + HDR_LEN_12, HDR_LEN);
+ int32_t chunkLen;
+ chunkLen = input.readInt32();
+ // check that chunk length is valid.
+ GF_DEV_ASSERT(chunkLen > 0);
+ isLastChunk = input.read();
+
+ uint8_t* chunk_body;
+ _GEODE_NEW(chunk_body, uint8_t[chunkLen]);
+ error = receiveData(reinterpret_cast<char*>(chunk_body), chunkLen,
+ receiveTimeoutSec, true, false);
if (error != CONN_NOERR) {
+ delete[] chunk_body;
if (error & CONN_TIMEOUT) {
throwException(TimeoutException(
"TcrConnection::readMessageChunked: "
- "connection timed out while receiving chunk header"));
+ "connection timed out while receiving chunk body"));
} else {
throwException(GeodeIOException(
"TcrConnection::readMessageChunked: "
- "connection failure while receiving chunk header"));
+ "connection failure while receiving chunk body"));
}
}
- } else {
- first = false;
- }
- ++chunkNum;
-
- LOGDEBUG(
- "TcrConnection::readMessageChunked: received chunk header %d "
- "from endpoint %s; bytes: %s",
- chunkNum, m_endpoint,
- Utils::convertBytesToString((msg_header + HDR_LEN_12), HDR_LEN)
-
- .c_str());
-
- auto input = m_connectionManager->getCacheImpl()->createDataInput(
- msg_header + HDR_LEN_12, HDR_LEN);
- int32_t chunkLen;
- chunkLen = input.readInt32();
- // check that chunk length is valid.
- GF_DEV_ASSERT(chunkLen > 0);
- isLastChunk = input.read();
-
- uint8_t* chunk_body;
- _GEODE_NEW(chunk_body, uint8_t[chunkLen]);
- error = receiveData(reinterpret_cast<char*>(chunk_body), chunkLen,
- receiveTimeoutSec, true, false);
- if (error != CONN_NOERR) {
- delete[] chunk_body;
- if (error & CONN_TIMEOUT) {
- throwException(TimeoutException(
- "TcrConnection::readMessageChunked: "
- "connection timed out while receiving chunk body"));
- } else {
- throwException(
- GeodeIOException("TcrConnection::readMessageChunked: "
- "connection failure while receiving chunk body"));
- }
- }
- LOGDEBUG(
- "TcrConnection::readMessageChunked: received chunk body %d "
- "from endpoint %s; bytes: %s",
- chunkNum, m_endpoint,
- Utils::convertBytesToString(chunk_body, chunkLen).c_str());
- // Process the chunk; the actual processing is done by a separate thread
- // ThinClientBaseDM::m_chunkProcessor.
-
- reply.processChunk(chunk_body, chunkLen,
- m_endpointObj->getDistributedMemberID(), isLastChunk);
- } while (!(isLastChunk & 0x1));
+ LOGDEBUG(
+ "TcrConnection::readMessageChunked: received chunk body %d "
+ "from endpoint %s; bytes: %s",
+ chunkNum, m_endpoint,
+ Utils::convertBytesToString(chunk_body, chunkLen).c_str());
+ // Process the chunk; the actual processing is done by a separate thread
+ // ThinClientBaseDM::m_chunkProcessor.
+
+ reply.processChunk(chunk_body, chunkLen,
+ m_endpointObj->getDistributedMemberID(), isLastChunk);
+ } while (!(isLastChunk & 0x1));
+ } catch (const Exception&) {
+ auto ex = reply.getChunkedResultHandler()->getException();
+ LOGDEBUG("Found existing exception ", ex->what());
+ reply.getChunkedResultHandler()->clearException();
+ throw;
+ }
LOGFINER(
"TcrConnection::readMessageChunked: read full reply "
diff --git a/tests/javaobject/NonDeserializableObject.java b/tests/javaobject/NonDeserializableObject.java
new file mode 100644
index 0000000..786c71a
--- /dev/null
+++ b/tests/javaobject/NonDeserializableObject.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package javaobject;
+
+import org.apache.geode.DataSerializable;
+import org.apache.geode.Instantiator;
+import org.apache.geode.cache.Declarable;
+import java.io.*;
+
+//
+// NonDeserializableObject is, in general, deserializable, but on a Geode server
+// it can't be deserialized because it has no default ctor, and thus can't be
+// instantiated via reflection. This is interesting because it's possible to,
+// for instance, execute a function server-side which returns an instance of
+// this class, which causes Geode to return a payload of type 'DataSerializable'
+// with subtype 'Class', and the class name and data necessary to recreate the
+// object in a client whieh supports reflection. Since C++ doesn't have this,
+// the Geode Native Client should throw an exception, and that's what we use
+// this class to test.
+//
+public class NonDeserializableObject implements DataSerializable {
+ static {
+ Instantiator.register(new NonDeserializableObjectInstantiator());
+ }
+
+ String m_str;
+
+ public NonDeserializableObject(String str){m_str = str;}
+
+ @Override
+ public void toData(DataOutput dataOutput) throws IOException {
+ }
+
+ @Override
+ public void fromData(DataInput dataInput) throws IOException, ClassNotFoundException {
+ }
+
+ public static class NonDeserializableObjectInstantiator extends Instantiator {
+ public NonDeserializableObjectInstantiator() {
+ super(NonDeserializableObject.class, 500);
+ }
+
+ public NonDeserializableObjectInstantiator(Class<? extends DataSerializable> c, int classId) {
+ super(c, classId);
+ }
+
+ @Override
+ public DataSerializable newInstance() {
+ return new NonDeserializableObject("foo");
+ }
+ }
+}
+
diff --git a/tests/javaobject/executeFunction_SendObjectWhichCantBeDeserialized.java b/tests/javaobject/executeFunction_SendObjectWhichCantBeDeserialized.java
new file mode 100644
index 0000000..69aa716
--- /dev/null
+++ b/tests/javaobject/executeFunction_SendObjectWhichCantBeDeserialized.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package javaobject;
+
+import org.apache.geode.DataSerializable;
+import org.apache.geode.Instantiator;
+import org.apache.geode.cache.Declarable;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.execute.Function;
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.RegionFunctionContext;
+
+import java.util.Properties;
+import java.io.*;
+
+import javaobject.NonDeserializableObject;
+
+public class executeFunction_SendObjectWhichCantBeDeserialized implements Function, Declarable {
+
+ public static final String NAME = "executeFunction_SendObjectWhichCantBeDeserialized";
+
+ @Override
+ public void execute(FunctionContext context) {
+ NonDeserializableObject myNonDeserializableObject = new NonDeserializableObject("123");
+ context.getResultSender().lastResult(myNonDeserializableObject);
+ }
+
+ @Override
+ public boolean hasResult() {
+ return true;
+ }
+
+ @Override
+ public boolean optimizeForWrite() {
+ return true;
+ }
+
+ @Override
+ public String getId() {
+ return NAME;
+ }
+
+ @Override
+ public boolean isHA() {
+ return true;
+ }
+
+ @Override
+ public void init(Properties props) {
+ }
+}
+