blob: 1d37301aed9197f2755937ef531cd63348d5a044 [file] [log] [blame]
/*
* 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 org.apache.ignite.transactions.spring.examples;
import java.io.Serializable;
import java.util.Objects;
import org.apache.ignite.client.ClientCache;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import static org.springframework.transaction.annotation.Isolation.READ_COMMITTED;
import static org.springframework.transaction.annotation.Isolation.REPEATABLE_READ;
/**
* Represents Spring Service that uses Ignite thin client to access Ignite cluster and perform cache transactional
* operations.
*/
@Service
public class IgniteClientTransactionalService {
/** Ignite cache representation that uses thin client to communicate with Ignite cluster. */
private ClientCache<String, Account> cache;
/**
* The emitters transfer the specified funds to the broker. When both funds are received, they are transferred to
* the recipient, excluding the fee which the broker keeps for himself. If an error occurs at any step of this
* operation, it is rolled back.
*/
@Transactional(isolation = REPEATABLE_READ)
public void transferFundsWithBroker(
String firstEmitter,
String secondEmitter,
String recipient,
String broker,
int funds,
int fee
) {
transferFunds(firstEmitter, broker, funds);
transferFunds(secondEmitter, broker, funds);
transferFunds(broker, recipient, funds * 2 - fee);
}
/** Transfers funds between two accounts that belong to users with the specified names. */
@Transactional(isolation = REPEATABLE_READ)
public void transferFunds(String emitter, String recipient, int funds) {
Account emitterAcc = cache.get(emitter);
Account recipientAcc = cache.get(recipient);
if (emitterAcc.balance < funds)
throw new RuntimeException("Insufficient funds in " + emitter + "'s account");
emitterAcc.balance -= funds;
recipientAcc.balance += funds;
saveAccount(emitterAcc);
saveAccount(recipientAcc);
System.out.println(">>> " + emitter + " transfers " + funds + " coins to " + recipient);
}
/** Gets current balance of the account with the specified name.*/
@Transactional(isolation = READ_COMMITTED)
public int getBalance(String login) {
return cache.get(login).balance;
}
/** Creates account with the specified user login and balance. */
public Account createAccount(String login, int balance) {
Account acc = new Account(login);
acc.balance = balance;
cache.put(login, acc);
return acc;
}
/** Sets an Ignite cache representation that uses thin client to communicate with the Ignite cluster. */
public void setCache(ClientCache<String, Account> cache) {
this.cache = cache;
}
/** Puts the specified account into the cache. */
private void saveAccount(Account acc) {
cache.put(acc.login, acc);
}
/** Represents the user account. */
private static class Account implements Serializable {
/** Account owner login. */
private final String login;
/** Balance. */
private int balance;
/** Creates an account with the specified owner name. */
public Account(String login) {
this.login = login;
}
/** {@inheritDoc} */
@Override public boolean equals(Object other) {
if (this == other)
return true;
if (other == null || getClass() != other.getClass())
return false;
Account acc = (Account)other;
return balance == acc.balance && Objects.equals(login, acc.login);
}
/** {@inheritDoc} */
@Override public int hashCode() {
return Objects.hash(login, balance);
}
}
}