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 NonReplicatedBankServer2
64 implements Bank, TransactionParticipant, ServiceIDListener
65 {
66
67
68
69
70
71 private static final Logger log = Logger.getLogger(NonReplicatedBankServer2.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 NonReplicatedBankServer2(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", "Bank/YadaSavings");
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
128 String[] groups = new String[] {System.getProperty("bank.lookup.group", "jgroup.sf.net")};
129 LookupDiscovery ld = new LookupDiscovery(groups);
130 new JoinManager(proxy, entries, this, ld, null);
131
132 initDB();
133 }
134
135
136
137
138
139
140
141
142
143 public Integer getBalance(long accNumber)
144 throws RemoteException
145 {
146 Integer balance = accounts.get(new Long(accNumber));
147 if (balance == null) balance = new Integer(0);
148 return balance;
149 }
150
151
152
153
154
155 public void withdraw(long accountNumber, int amount, long transactionID)
156 throws RemoteException
157 {
158
159 log.debug("Withdraw=" + amount + ",Account=" + accountNumber + ",tid=" + transactionID);
160 }
161
162
163
164
165
166 public void deposit(long accountNumber, int amount, long transactionID)
167 throws RemoteException
168 {
169
170 log.debug("Deposit=" + amount + ",Account=" + accountNumber + ",tid=" + transactionID);
171 }
172
173
174
175
176
177 public String getName()
178 throws RemoteException
179 {
180 return name;
181 }
182
183
184
185
186
187
188
189
190
191 private void doCreditDebit(long accNumber, int credit, int debit)
192 {
193
194 Account account = getAccount(pm, accNumber);
195
196 int newBalance = account.getBalance();
197 newBalance += credit;
198 newBalance -= debit;
199 updateAccount(pm, accNumber, newBalance);
200
201
202 }
203
204
205
206
207
208
209
210
211
212 public int prepare(TransactionManager mgr, long id)
213 throws UnknownTransactionException, RemoteException
214 {
215 log.debug(name + " reached PREPARE state, txn id:" + id);
216 return TransactionConstants.PREPARED;
217 }
218
219
220
221
222
223 public void commit(TransactionManager mgr, long id)
224 throws UnknownTransactionException, RemoteException
225 {
226 log.debug(name + " reached COMMIT state, txn id: " + id);
227
228
229
230
231
232
233
234 }
235
236
237
238
239
240 public void abort(TransactionManager mgr, long id)
241 throws UnknownTransactionException, RemoteException
242 {
243 log.debug(name + " reached ABORT state for txn id: " + id);
244
245
246
247
248 }
249
250
251
252
253
254 public int prepareAndCommit(TransactionManager mgr, long id)
255 throws UnknownTransactionException, RemoteException
256 {
257 int result = prepare(mgr, id);
258 if (result == TransactionConstants.PREPARED) {
259 commit(mgr, id);
260 result = TransactionConstants.COMMITTED;
261 }
262 return result;
263 }
264
265
266
267
268
269
270
271
272
273 private void initDB()
274 {
275 String syspmf = System.getProperty("javax.jdo.PersistenceManagerFactoryClass",
276 "com.objectdb.jdo.PMF");
277
278 String connectionURL = System.getProperty("bank2.connectionURL", "/tmp/bank2.odb");
279
280 log.debug("syspmf: " + syspmf);
281 log.debug("connectionURL: " + connectionURL);
282
283 Properties properties = new Properties();
284 properties.setProperty(
285 "javax.jdo.PersistenceManagerFactoryClass", syspmf);
286 properties.setProperty(
287 "javax.jdo.option.ConnectionURL", connectionURL);
288
289 pmf = JDOHelper.getPersistenceManagerFactory(properties,
290 JDOHelper.class.getClassLoader());
291
292
293 Account account = null;
294 account = getAccount(pm, 111111111);
295 if (account == null) {
296 for (int i=1; i < 10; i++) {
297 insertAccount(pm, 111111111*i, 100000);
298 }
299 }
300 }
301
302
303
304
305
306
307
308
309
310 private void insertAccount(PersistenceManager pm, long number, int balance)
311 {
312 Account account = new Account(number, balance);
313 try {
314 pm = pmf.getPersistenceManager();
315 pm.currentTransaction().begin();
316 pm.makePersistent(account);
317 pm.currentTransaction().commit();
318 } catch (Exception e) {
319 pm.currentTransaction().rollback();
320 log.error(e.getMessage());
321 } finally {
322 pm.close();
323 }
324 }
325
326
327
328
329
330
331
332
333
334 private boolean updateAccount(PersistenceManager pm, long number, int balance)
335 {
336 Account account = null;
337 boolean update = true;
338
339 try {
340 pm = pmf.getPersistenceManager();
341 pm.currentTransaction().begin();
342 Query query = pm.newQuery(Account.class, "number == " + number);
343
344 Collection result = (Collection) query.execute();
345
346 account = (Account) result.iterator().next();
347
348 if (account == null) {
349 update = false;
350 log.debug("Did not find a matching instance");
351 pm.currentTransaction().rollback();
352 }
353
354 account.setBalance(balance);
355 pm.currentTransaction().commit();
356 } catch (Exception e) {
357 pm.currentTransaction().rollback();
358 log.error(e.getMessage());
359 } finally {
360 pm.close();
361 }
362 return update;
363 }
364
365
366
367
368
369
370
371
372
373 private Account getAccount(PersistenceManager pm, long number)
374 {
375 Account account = null;
376
377 try {
378 pm = pmf.getPersistenceManager();
379
380 Query query = pm.newQuery(Account.class, "number == " + number);
381
382 Collection result = (Collection) query.execute();
383
384 account = (Account) result.iterator().next();
385
386 if (account == null) {
387 log.debug("Did not find a matching instance");
388 pm.currentTransaction().rollback();
389 }
390 } catch (Exception e) {
391 log.error(e.getMessage());
392 } finally {
393 pm.close();
394 }
395 return account;
396 }
397
398
399
400
401
402
403
404
405
406 public class CreditDebit implements Serializable
407 {
408 private static final long serialVersionUID = 1570639001656522420L;
409 int credit;
410 int debit;
411 long accNumber;
412
413 CreditDebit(long accNumber, int credit, int debit)
414 {
415 this.accNumber = accNumber;
416 this.credit = credit;
417 this.debit = debit;
418 }
419
420 public String toString()
421 {
422 String temp = "CreditDebit { \n";
423 temp += "accNumber=" + accNumber + "\n";
424 temp += "credit=" + credit + "\n";
425 temp += "debit=" + debit + "\n";
426 temp += "} \n";
427 return temp;
428 }
429 }
430
431
432
433
434
435
436
437
438
439 public void serviceIDNotify(ServiceID serviceID)
440 {
441 log.debug("Service ID: " + serviceID);
442 }
443
444 }