1 /*-----------------------------------------------------------------------------
2 Name: TestRequestResponse.cpp
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 Comment: Demo code for a client using xmlBlaster
6 build -DexeName=TestRequestResponse cpp-test-single
7 -----------------------------------------------------------------------------*/
8 #include "TestSuite.h"
9 #include <iostream>
10
11 /**
12 * This client tests the request/reply pattern
13 */
14
15 using namespace std;
16 using namespace org::xmlBlaster::util;
17 using namespace org::xmlBlaster::util::qos;
18 using namespace org::xmlBlaster::util::thread;
19 using namespace org::xmlBlaster::client;
20 using namespace org::xmlBlaster::client::qos;
21 using namespace org::xmlBlaster::client::key;
22 using namespace org::xmlBlaster::authentication;
23
24 namespace org { namespace xmlBlaster { namespace test {
25
26 /**
27 * Callback implementation of the receiver client.
28 */
29 class ReceiverCallback : public I_Callback {
30 private:
31 XmlBlasterAccess &receiver_;
32 string name_;
33 I_Log& log_;
34
35 public:
36 ReceiverCallback(XmlBlasterAccess &receiver, I_Log& log, const string& name) : receiver_(receiver), log_(log) {
37 name_ = name;
38 }
39
40 string update(const string &sessionId,
41 UpdateKey &updateKey,
42 const unsigned char * /*content*/, long /*contentSize*/,
43 UpdateQos &updateQos)
44 {
45 log_.info("update", string("Receiving update on callback '") + name_ + "' of message oid=" +
46 updateKey.getOid() + " state=" + updateQos.getState() +
47 " authentication sessionId=" + sessionId + " ...");
48
49 //if (updateKey.isInternal()) return "";
50 if (updateQos.isErased()) return "";
51
52 try {
53 string tempTopicOid = updateQos.getClientProperty(Constants::JMS_REPLY_TO, string("")); // __jms:JMSReplyTo
54 log_.info("update", name_+": Got request, using topic '" + tempTopicOid + "' for response");
55
56 // Send reply back ...
57 PublishKey pk(receiver_.getGlobal(), tempTopicOid, "text/plain", "1.0");
58 PublishQos pq(receiver_.getGlobal());
59 MessageUnit msgUnit(pk, "On doubt no ultimate truth, my dear.", pq);
60 PublishReturnQos retQos = receiver_.publish(msgUnit);
61 log_.info("update", name_+": Published reply message using temporary topic " + retQos.getKeyOid());
62 }
63 catch (XmlBlasterException &e) {
64 log_.error("update", string(name_)+": Sending reply to " + updateQos.getSender()->getAbsoluteName() + " failed: " + e.getMessage());
65 }
66 return "<qos><state id='OK'/></qos>";
67 }
68 };
69
70
71 class TestRequestResponse: public TestSuite, public virtual I_Callback
72 {
73 private:
74 bool messageArrived_; // = false;
75 string subscribeOid_;
76 string publishOid_; // = "dummy";
77 string senderName_;
78 string receiverName_; // sender/receiver is here the same client
79 ConnectReturnQos returnQos_;
80 ReceiverCallback *cbReceiver;
81
82 GlobalRef globalReceiver_;
83 XmlBlasterAccess receiver_;
84
85 /**
86 * Constructs the TestRequestResponse object.
87 * <p />
88 * @param testName The name used in the test suite
89 * @param loginName The name to login to the xmlBlaster
90 */
91 public:
92 TestRequestResponse(int args, char *argc[], const string &senderName, const string &receiverName)
93 : TestSuite(args, argc, "TestRequestResponse"),
94 returnQos_(global_),
95 globalReceiver_(global_.createInstance("receiverGlobal")),
96 receiver_(globalReceiver_)
97 {
98 globalReceiver_->initialize(args, argc);
99 senderName_ = senderName;
100 receiverName_ = receiverName;
101 publishOid_ = "dummy";
102 cbReceiver = new ReceiverCallback(receiver_, log_, "callbackReceiver");
103 }
104
105 virtual ~TestRequestResponse()
106 {
107 delete cbReceiver;
108 }
109
110 /**
111 * Sets up the fixture. <p />
112 * Connect to xmlBlaster and login
113 */
114 void setUp()
115 {
116 log_.info(ME, "Trying to connect to xmlBlaster with C++ client lib " + Global::getVersion() + " from " + Global::getBuildTimestamp());
117 TestSuite::setUp();
118 const string passwd = "secret";
119 try {
120 ConnectQos connQos(global_, senderName_);
121 returnQos_ = connection_.connect(connQos, this);
122 log_.info(ME, string("connected '") + senderName_ + "'");
123 }
124 catch (XmlBlasterException &e) {
125 log_.error(ME, string("Login failed: ") + e.toXml());
126 usage();
127 assert(0);
128 }
129
130 try {
131 ConnectQos connQos(receiver_.getGlobal(), receiverName_);
132 returnQos_ = receiver_.connect(connQos, cbReceiver);
133 log_.info(ME, string("connected '") + receiverName_ + "'");
134 }
135 catch (XmlBlasterException &e) {
136 log_.error(ME, string("Login failed: ") + e.toXml());
137 usage();
138 assert(0);
139 }
140 }
141
142
143 /**
144 * Tears down the fixture. <p />
145 * cleaning up .... erase() the previous message OID and logout
146 */
147 void tearDown()
148 {
149 log_.info(ME, "Cleaning up test");
150 connection_.disconnect(DisconnectQos(global_));
151 receiver_.disconnect(DisconnectQos(receiver_.getGlobal()));
152 TestSuite::tearDown();
153 }
154
155 /**
156 * TEST
157 */
158 void testRequest()
159 {
160 if (log_.trace()) log_.trace(ME, "Publishing a message (old style) ...");
161 PublishKey pubKey(global_, "requestForEnlightenment");
162 PublishQos pubQos(global_);
163 Destination destination(global_, receiverName_);
164 pubQos.addDestination(destination);
165 MessageUnit msgUnit(pubKey, "Tell me the truth!", pubQos);
166 try {
167 std::vector<org::xmlBlaster::util::MessageUnit> replies =
168 connection_.request(msgUnit, 6000, 1);
169 assertEquals(log_, ME, 1, replies.size(), "missing response");
170 log_.info(ME, senderName_+": Got " + lexical_cast<string>(replies.size()) + " reply :\n" + replies[0].toXml());
171 log_.info(ME, replies[0].getContentStr() + " size=" + lexical_cast<string>(replies[0].getContentLen()));
172 assertEquals(log_, ME, "On doubt no ultimate truth, my dear.", replies[0].getContentStr(), "response from a wise man");
173 }
174 catch(XmlBlasterException &e) {
175 log_.warn(ME, string("XmlBlasterException: ")+e.toXml());
176 assert(0);
177 }
178 }
179
180 string update(const string &sessionId,
181 UpdateKey &updateKey,
182 const unsigned char *content, long contentSize,
183 UpdateQos &updateQos)
184 {
185 log_.error(ME, string("Unexpected receiving update of message oid=") +
186 updateKey.getOid() + " state=" + updateQos.getState() +
187 " authentication sessionId=" + sessionId + " ...");
188 return "<qos><state id='OK'/></qos>";
189 }
190
191
192 /**
193 * Little helper, waits until the variable 'messageArrive' is set
194 * to true, or returns when the given timeout occurs.
195 * @param timeout in milliseconds
196 */
197 private:
198 void usage() const
199 {
200 TestSuite::usage();
201 log_.plain(ME, "----------------------------------------------------------");
202 log_.plain(ME, "Testing C++ request/reply pattern");
203 log_.plain(ME, "Usage:");
204 XmlBlasterAccess::usage();
205 log_.usage();
206 log_.plain(ME, "Example:");
207 log_.plain(ME, " TestRequestResponse -trace true");
208 log_.plain(ME, "----------------------------------------------------------");
209 }
210 };
211
212 }}} // namespace
213
214 using namespace org::xmlBlaster::test;
215
216 int main(int args, char *argc[])
217 {
218 try {
219 org::xmlBlaster::util::Object_Lifetime_Manager::init();
220 TestRequestResponse testReq(args, argc, "TheDesperate", "TheKnowing");
221
222 testReq.setUp();
223 testReq.testRequest();
224 testReq.tearDown();
225
226 Thread::sleepSecs(1);
227 }
228 catch (XmlBlasterException& ex) {
229 std::cout << ex.toXml() << std::endl;
230 }
231 catch (bad_exception& ex) {
232 cout << "bad_exception: " << ex.what() << endl;
233 }
234 catch (exception& ex) {
235 cout << " exception: " << ex.what() << endl;
236 }
237 catch (string& ex) {
238 cout << "string: " << ex << endl;
239 }
240 catch (char* ex) {
241 cout << "char* : " << ex << endl;
242 }
243
244 catch (...)
245 {
246 cout << "unknown exception occured" << endl;
247 XmlBlasterException e(INTERNAL_UNKNOWN, "main", "main thread");
248 cout << e.toXml() << endl;
249 }
250
251 org::xmlBlaster::util::Object_Lifetime_Manager::fini();
252 return 0;
253 }
syntax highlighted by Code2HTML, v. 0.9.1