1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package jgroup.test.jini.txn;
19
20 import java.io.Serializable;
21 import java.rmi.Remote;
22 import java.rmi.RemoteException;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.Map;
27 import java.util.Properties;
28
29 import javax.jdo.JDOHelper;
30 import javax.jdo.PersistenceManager;
31 import javax.jdo.PersistenceManagerFactory;
32 import javax.jdo.Query;
33
34 import jgroup.core.ConfigManager;
35 import net.jini.config.Configuration;
36 import net.jini.config.ConfigurationProvider;
37 import net.jini.core.entry.Entry;
38 import net.jini.core.lookup.ServiceID;
39 import net.jini.core.transaction.UnknownTransactionException;
40 import net.jini.core.transaction.server.TransactionConstants;
41 import net.jini.core.transaction.server.TransactionManager;
42 import net.jini.core.transaction.server.TransactionParticipant;
43 import net.jini.discovery.LookupDiscovery;
44 import net.jini.export.Exporter;
45 import net.jini.jeri.BasicILFactory;
46 import net.jini.jeri.BasicJeriExporter;
47 import net.jini.jeri.tcp.TcpServerEndpoint;
48 import net.jini.lookup.JoinManager;
49 import net.jini.lookup.ServiceIDListener;
50 import net.jini.lookup.entry.Name;
51
52 import org.apache.log4j.Logger;
53
54 import com.sun.jini.config.Config;
55 import com.sun.jini.start.LifeCycle;
56
57
58
59
60
61
62
63 public class NonReplicatedBankServer
64 implements Bank, TransactionParticipant, ServiceIDListener
65 {
66
67
68
69
70
71 private static final Logger log = Logger.getLogger(NonReplicatedBankServer.class);
72
73
74
75
76
77
78
79 private Map<Long, CreditDebit> pendingTxns;
80 private Map<Integer, Integer> accounts;
81
82
83 private String name;
84
85
86 private PersistenceManagerFactory pmf;
87 private PersistenceManager pm;
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 public NonReplicatedBankServer(String[] configArgs, LifeCycle lifeCycle)
110 throws Exception
111 {
112 ConfigManager.init();
113
114 pendingTxns = Collections.synchronizedMap(new HashMap<Long, CreditDebit>());
115 accounts = Collections.synchronizedMap(new HashMap<Integer, Integer>());
116
117 name = System.getProperty("bank.name", "NOKAS/RobberyBank");
118
119 Entry[] entries = new Entry[] { new Name(name) };
120 final Configuration config = ConfigurationProvider.getInstance(configArgs, getClass()
121 .getClassLoader());
122 Exporter exporter = (Exporter) Config.getNonNullEntry(config, "jgroup.test.jini.txn",
123 "serverExporter", Exporter.class,
124 new BasicJeriExporter(TcpServerEndpoint.getInstance(0), new BasicILFactory()));
125
126 Remote proxy = exporter.export(this);
127 String[] groups = new String[] {System.getProperty("bank.lookup.group", "jgroup.sf.net")};
128 LookupDiscovery ld = new LookupDiscovery(groups);
129 new JoinManager(proxy, entries, this, ld, null);
130
131 initDB();
132 }
133
134
135
136
137
138
139
140
141
142 public Integer getBalance(long accNumber)
143 throws RemoteException
144 {
145 Integer balance = accounts.get(new Long(accNumber));
146 if (balance == null) balance = new Integer(0);
147 return balance;
148 }
149
150
151
152
153
154 public void withdraw(long accountNumber, int amount, long transactionID)
155 throws RemoteException
156 {
157
158 log.debug("Withdraw=" + amount + ",Account=" + accountNumber + ",tid=" + transactionID);
159 }
160
161
162
163
164
165 public void deposit(long accountNumber, int amount, long transactionID)
166 throws RemoteException
167 {
168
169 log.debug("Deposit=" + amount + ",Account=" + accountNumber + ",tid=" + transactionID);
170 }
171
172
173
174
175
176 public String getName()
177 throws RemoteException
178 {
179 return name;
180 }
181
182
183
184
185
186
187
188
189
190 private void doCreditDebit(long accNumber, int credit, int debit)
191 {
192
193 Account account = getAccount(pm, accNumber);
194
195 int newBalance = account.getBalance();
196 newBalance += credit;
197 newBalance -= debit;
198 updateAccount(pm, accNumber, newBalance);
199
200 }
201
202
203
204
205
206
207
208
209
210 public int prepare(TransactionManager mgr, long id)
211 throws UnknownTransactionException, RemoteException
212 {
213 log.debug(name + " reached PREPARE state, txn id:" + id);
214 return TransactionConstants.PREPARED;
215 }
216
217
218
219
220
221 public void commit(TransactionManager mgr, long id)
222 throws UnknownTransactionException, RemoteException
223 {
224 log.debug(name + " reached COMMIT state, txn id: " + id);
225
226
227
228
229
230
231
232 }
233
234
235
236
237
238 public void abort(TransactionManager mgr, long id)
239 throws UnknownTransactionException, RemoteException
240 {
241 log.debug(name + " reached ABORT state for txn id: " + id);
242
243
244
245
246 }
247
248
249
250
251
252 public int prepareAndCommit(TransactionManager mgr, long id)
253 throws UnknownTransactionException, RemoteException
254 {
255 int result = prepare(mgr, id);
256 if (result == TransactionConstants.PREPARED) {
257 commit(mgr, id);
258 result = TransactionConstants.COMMITTED;
259 }
260 return result;
261 }
262
263
264
265
266
267
268
269
270
271 private void initDB()
272 {
273 String syspmf = System.getProperty("javax.jdo.PersistenceManagerFactoryClass",
274 "com.objectdb.jdo.PMF");
275 String connectionURL = System.getProperty("bank.connectionURL", "/tmp/bank.odb");
276
277 log.debug("syspmf: " + syspmf);
278 log.debug("connectionURL: " + connectionURL);
279
280 Properties properties = new Properties();
281 properties.setProperty(
282 "javax.jdo.PersistenceManagerFactoryClass", syspmf);
283 properties.setProperty(
284 "javax.jdo.option.ConnectionURL", connectionURL);
285
286 pmf = JDOHelper.getPersistenceManagerFactory(properties,
287 JDOHelper.class.getClassLoader());
288
289
290 Account account = null;
291 account = getAccount(pm, 111111111);
292 if (account == null) {
293 for (int i=1; i < 10; i++) {
294 insertAccount(pm, 111111111*i, 100000);
295 }
296 }
297 }
298
299
300
301
302
303
304
305
306
307 private void insertAccount(PersistenceManager pm, long number, int balance)
308 {
309 Account account = new Account(number, balance);
310 try {
311 pm = pmf.getPersistenceManager();
312 pm.currentTransaction().begin();
313 pm.makePersistent(account);
314 pm.currentTransaction().commit();
315 } catch (Exception e) {
316 pm.currentTransaction().rollback();
317 log.error(e.getMessage());
318 } finally {
319 pm.close();
320 }
321 }
322
323
324
325
326
327
328
329
330
331 private boolean updateAccount(PersistenceManager pm, long number, int balance)
332 {
333 Account account = null;
334 boolean update = true;
335
336 try {
337 pm = pmf.getPersistenceManager();
338 pm.currentTransaction().begin();
339 Query query = pm.newQuery(Account.class, "number == " + number);
340
341 Collection result = (Collection) query.execute();
342
343 account = (Account) result.iterator().next();
344
345 if (account == null) {
346 update = false;
347 log.debug("Did not find a matching instance");
348 pm.currentTransaction().rollback();
349 }
350
351 account.setBalance(balance);
352 pm.currentTransaction().commit();
353 } catch (Exception e) {
354 pm.currentTransaction().rollback();
355 log.error(e.getMessage());
356 } finally {
357 pm.close();
358 }
359 return update;
360 }
361
362
363
364
365
366
367
368
369
370 private Account getAccount(PersistenceManager pm, long number)
371 {
372 Account account = null;
373
374 try {
375 pm = pmf.getPersistenceManager();
376
377 Query query = pm.newQuery(Account.class, "number == " + number);
378
379 Collection result = (Collection) query.execute();
380
381 account = (Account) result.iterator().next();
382
383 if (account == null) {
384 log.debug("Did not find a matching instance");
385 pm.currentTransaction().rollback();
386 }
387 } catch (Exception e) {
388 log.error(e.getMessage());
389 } finally {
390 pm.close();
391 }
392 return account;
393 }
394
395
396
397
398
399
400
401
402
403 public class CreditDebit implements Serializable
404 {
405 private static final long serialVersionUID = -923925461553488080L;
406 int credit;
407 int debit;
408 long accNumber;
409
410 CreditDebit(long accNumber, int credit, int debit)
411 {
412 this.accNumber = accNumber;
413 this.credit = credit;
414 this.debit = debit;
415 }
416
417 public String toString()
418 {
419 String temp = "CreditDebit { \n";
420 temp += "accNumber=" + accNumber + "\n";
421 temp += "credit=" + credit + "\n";
422 temp += "debit=" + debit + "\n";
423 temp += "} \n";
424 return temp;
425 }
426 }
427
428
429
430
431
432
433
434
435
436 public void serviceIDNotify(ServiceID serviceID)
437 {
438 log.debug("Service ID: " + serviceID);
439 }
440
441 }
442