π Chapter 11: 첫 ν μ€νΈ ν΅κ³ΌνκΈ°
π ν μ€νΈ λꡬ ꡬμΆβ
- ν
μ€νΈ κΈ°λ° κ΅¬μ‘°μ μ¬μ©λ λ κ°μ μ»΄ν¬λνΈ, μ¦
ApplicationRunner
μFakeAuctionServer
λ₯Ό μμ±ν μΌμ΄ λ¨λλ€.
π μ ν리μΌμ΄μ λ¬λβ
ApplicationRunner
λ νμ¬ λ§λ€κ³ μλ μ€μ μ ν리μΌμ΄μ κ³Ό κ΄λ¦¬ λ° ν΅μ μ μ΄κ΄νλ κ°μ²΄λ€.ApplicationRunner
λ λ§μΉ λͺ λ Ήμ€μμ μ€νλ κ²μ²λΌ μ ν리μΌμ΄μ μ μ€ννκ³ GUI μνλ₯Ό μ‘°ννκ³ ν μ€νΈκ° λλ λ μ ν리μΌμ΄μ μ μ’ λ£νκΈ° μν΄ λ©μΈ μ°½μ λν μ°Έμ‘°λ₯Ό νλν΄μ 보κ΄νλ€.- μλ ν μ€νΈλ νΉμ λ¬Έμμ΄μ 보μ¬μ£Όλ λ μ΄λΈ μ»΄ν¬λνΈλ₯Ό μ°Ύλλ° μ ν리μΌμ΄μ μμ μ΄ λ μ΄λΈμ λ§λ€μ΄λ΄μ§ μλλ€λ©΄ μμΈκ° λ°μ ν κ²μ΄λ€.
public class ApplicationRunner {
public static final String SNIPER_ID = "sniper";
public static final String SNIPER_PASSWORD = "sniper";
private AuctionSniperDriver driver;
public void startBiddingIn(final FakeAuctionServer auction) {
Thread thread = new Thread("Test Application") {
// μ½λμ κ° λΆλΆμ μ¬λ°λ₯΄κ² μ‘°ν©νλμ§ νμΈνκ³ μ μ ν리μΌμ΄μ
μ main ν¨μλ₯Ό ν΅ν΄ μ ν리μΌμ΄μ
μ νΈμΆ
@Override public void run() {
try {
// ν νλͺ©μ λν΄μλ§ μ
μ°°νκ³ μλ³μλ₯Ό main()μΌλ‘ μ λ¬νλ€κ³ κ°μ νλ€.
Main.main(XMPP_HOSTNAME, SNIPER_ID, SNIPER_PASSWORD, auction.getItemId());
} catch (Exception e) {
// main()μμ μμΈλ₯Ό λμ§λ©΄ μ¬κΈ°μλ μμΈλ₯Ό μΆλ ₯νκΈ°λ§ νλ€.
e.printStackTrace();
}
}
};
thread.setDaemon(true);
thread.start();
// νλ μκ³Ό μ»΄ν¬λνΈλ₯Ό μ°ΎκΈ° μν΄ μ ν μκ° μ£ΌκΈ°λ₯Ό μ€μλ€.
driver = new AuctionSniperDriver(1000);
// μ ν리μΌμ΄μ
μ΄ μ μμ μλνλμ§ νμ
νκ³ μ μνκ° JoiningμΌλ‘ λ°λκΈΈ κΈ°λ€λ¦°λ€.
// μ΄ λ¨μ μ μ¬μ©μ μΈν°νμ΄μ€κ° μ΄λκ°μ μ€λμ΄νΌ μνλ₯Ό νμνλ λ μ΄λΈμ΄ μμμ λ§ν΄μ€λ€.
driver.showsSniperStatus(STATUS_JOINING);
}
public void showsSniperHasLostAuction() {
// μ€λμ΄νΌκ° 경맀μμ λμ°°νμ§ λͺ»νλ©΄ Lost μνλ₯Ό 보μ¬μ€ κ²μΌλ‘ μμνλ€.
driver.showsSniperStatus(STATUS_LOST);
}
public void stop() {
if (driver != null) {
// ν
μ€νΈκ° λλλ©΄ λλΌμ΄λ²κ° μ°½μ μμ κ² ν΄μ κ°λΉμ§ 컬λ μ
μ΄ μλ£λκΈ° μ μ λ€λ₯Έ ν
μ€νΈμμ μ°½μ μ¬μ©νλ κ²μ λ°©μ§νλ€.
driver.dispose();
}
}
}
π κ°μ§ 경맀β
FakeAuctionServer
λ λ체 μλ²λ‘μ, ν μ€νΈμμλFakeAuctionServer
λ₯Ό μ΄μ©ν΄ 경맀 μ€λμ΄νΌκ° μ΄λ»κ² XMPP λ©μμ§λ₯Ό μ¬μ©ν΄ 경맀μ μνΈ μμ©νλμ§ κ²μ¬ν μ μλ€.FakeAuctionServer
μλ μΈ κ°μ§ μ± μμ΄ μλ€.- XMPP λΈλ‘컀μ μ μν΄ μ€λμ΄νΌμμ μ±ν μ μ°Έμ¬νλΌλ μμ²μ μλ½ν΄μΌ νλ€.
- μ€λμ΄νΌλ‘λΆν° μ±ν λ©μμ§λ₯Ό λ°κ±°λ νΉμ μ ν μκ° λ΄μ μλ¬΄λ° λ©μμ§λ λ°μ§ λͺ»νλ©΄ μ€ν¨ν΄μΌ νλ€.
- μ¬μ°μ€λΉ μ¨λΌμΈμμ λͺ μν λλ‘ ν μ€νΈμμ μ€λμ΄νΌλ‘ λ©μμ§λ₯Ό λλλ € λ³΄λΌ μ μκ² ν΄μΌ νλ€.
public class FakeAuctionServer {
// μμ μλ΅..
private final String itemId;
private final XMPPConnection connection;
private Chat currentChat;
public FakeAuctionServer(String itemId) {
this.itemId = itemId;
this.connection = new XMPPConnection(XMPP_HOSTNAME);
}
public void startSellingItem() throws XMPPException {
// XMPP λΈλ‘μ»€λ‘ μ μ
connection.connect();
// νλͺ© μλ³μλ‘ λ‘κ·ΈμΈ μ΄λ¦μ μμ±
connection.login(format(ITEM_ID_AS_LOGIN, itemId), AUCTION_PASSWORD,AUCTION_RESOURCE);
// λ‘κ·ΈμΈ μ΄λ¦μ ChatManagerListenerμ λ±λ‘
connection.getChatManager().addChatListener(
new ChatManagerListener() {
public void chatCreated(Chat chat, boolean createdLocally) {
currentChat = chat;
}
}
);
}
public String getItemId() {
return itemId;
}
}
- λ©μμ§λ₯Ό λ°μΌλ‘λ©΄
chat
μMessageListener
λ₯Ό μΆκ°ν΄μΌ νλ€.
public class FakeAuctionServer {
// ...
private final SingleMessageListener messageListener = new SingleMessageListener();
// ...
public void startSellingItem() throws XMPPException {
// ...
connection.getChatManager().addChatListener(
new ChatManagerListener() {
public void chatCreated(Chat chat, boolean createdLocally) {
currentChat = chat;
chat.addMessageListener(messageListener);
}
}
);
}
// ...
public void hasReceivedJoinRequestFromSniper() throws InterruptedException {
// ν
μ€νΈμμ Join λ©μμ§κ° μΈμ λμ°©νλμ§ μ νμκ° μλ€. (μ΄ κ΅¬νμμ 5μ΄ μ΄λ΄)
messageListener.receivesAMessage();
}
public void announceClosed() throws XMPPException {
// ν
μ€νΈμμλ κ²½λ§€κ° μ’
λ£λ λ 경맀 μ’
λ£ μ μΈμ νλ΄ λΌ μ μμ΄μΌ νλ€.
currentChat.sendMessage(new Message());
}
public void stop() {
// μ°κ²° λ«κΈ°
connection.disconnect();
}
}
π ν μ€νΈ μ€ν¨μ ν΅κ³Όβ
π 첫 μ¬μ©μ μΈν°νμ΄μ€β
πΆ ν μ€νΈ μ€ν¨β
- ν
μ€νΈμμ
Auction Sniper Main
μ΄λΌλ μ¬μ©μ μΈν°νμ΄μ€ μ»΄ν¬λνΈλ₯Ό μ°Ύμ§ λͺ»νλ€.
πΆ ꡬνβ
- μμ μ ν리μΌμ΄μ μλ μ΅μμ μλκ° νμνλ€. μ¬κΈ°μλ μλλ₯Ό νλ λ§λ€κ³ μ μ ν μ΄λ¦λ§ λΆμ¬νλ€.
public class Main {
private MainWindow ui;
public Main() throws Exception {
startUserInterface();
}
public static void main(String... args) throws Exception {
Main main = new Main();
}
private void startUserInterface() throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
ui = new MainWindow();
}
});
}
}
public class MainWindow extends JFrame {
public MainWindow() {
super("Auction Sniper");
setName(MAIN_WINDOW_NAME);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
}
πΆ μ°Έκ³ β
- νμ¬ μ μ½λμ μ¬μ©μ μΈν°νμ΄μ€λ μ΅μνλμ΄μλ€. μ¬μ©μ μΈν°νμ΄μ€λ λ³κ² μμ§λ§ νμ€ν μ ν리μΌμ΄μ μλλ₯Ό μμνκ³ κ±° κΈ°μ μ°κ²°ν μ μλ€. ν μ€νΈλ μ¬μ ν μ€ν¨νμ§λ§ νκ±Έμ λ΄λλ μ μ΄λ€.
- μ΄μ ν μ€νΈ μ€λΉκ° λμνλ€λ μ¬μ€μ μ μ μμΌλ©°, μ΄λ‘μ¨ μ’ λ ν₯λ―Έλ‘μ΄ κΈ°λ₯μ ꡬννλ κ²μΌλ‘ λμκ° λ κ±±μ κ±°λ¦¬κ° νλ μ€μ΄λ μ μ΄λ€.
π μ€λμ΄νΌ μν νμβ
πΆ ν μ€νΈ μ€ν¨β
- ν μ€νΈμμλ μ΅μμ μλλ₯Ό μ°Ύμμ§λ§ μ€λμ΄νΌμ νμ¬ μνλ λνλ μμ§ μλ€.
- μ°μ μ€λμ΄νΌμμλ κ²½λ§€κ° μλ΅νκΈΈ κΈ°λ€λ¦¬λ λμ Joiningμ 보μ¬μ€μΌ νλ€.
πΆ ꡬνβ
MainWindow
μ μ€λμ΄νΌ μνλ₯Ό μΆκ°νλ λ μ΄λΈμ μΆκ°νλ€.
public class MainWindow extends JFrame {
public static final String SNIPER_STATUS_NAME = "sniper status";
private final JLabel sniperStatus = createLabel(STATUS_JOINING);
public MainWindow() {
super("Auction Sniper");
setName(MAIN_WINDOW_NAME);
add(sniperStatus);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
private static JLabel createLabel(String initialText) {
JLabel result = new JLabel(initialText);
result.setName(SNIPER_STATUS_NAME);
result.setBorder(new LineBorder(Color.BLACK));
return result;
}
}