Server.java

  1. import java.rmi.*;

    public interface Server extends Remote{

        public void send(String msg) throws RemoteException;
        public void register(Client client, String name) throws RemoteException;   
        public void unregister(Client client, String name) throws RemoteException;   
    }

 

ServerImpl.java

  1. import java.rmi.server.*;
    import java.rmi.*;
    import java.util.*;

    public class ServerImpl extends UnicastRemoteObject implements Server {
        Vector clientList;

        public ServerImpl() throws RemoteException {
            super();
            clientList = new Vector();
        }

        public synchronized void register(Client client, String name) throws RemoteException {
            clientList.add(client);
            send(name + "님이 입장하셨습니다.");
        }

        public void send(String msg) throws RemoteException {
            synchronized(clientList) {
                Enumeration e = clientList.elements();
                while( e.hasMoreElements() ) {
                    Client c = (Client)e.nextElement();
                    c.back(msg);
                }
            }
        }

        public synchronized void unregister(Client client, String name) throws RemoteException {
            clientList.removeElement(client);
            send(name + "님이 퇴장하셨습니다.");
        }

        public static void main(String[] args) {
            try {
                ServerImpl s = new ServerImpl();
                Naming.rebind("rmi://61.103.103.184/chat", s);
                System.out.println("RMI Chat Server is ready.");
            } catch ( Exception e ) {
                e.printStackTrace();       
            }

        }
    }

 

Client.java

  1. import java.rmi.*;

    public interface Client extends Remote {
        public void back(String msg) throws RemoteException ;
    }

 

ClientImpl.java

  1. import java.awt.*;
    import java.awt.event.*;
    import java.rmi.Naming;
    import java.rmi.server.UnicastRemoteObject;

    import javax.swing.*;

    public class ClientImpl extends JFrame implements Client, ActionListener {
        JTextArea display, display2;
        JTextField input, id;
        JLabel label, nick;
        Server    server;
        JButton    register, close, enter, clear;
        String name, serverName;
        CardLayout card;
        JPanel npanel;
       
        public ClientImpl() {
            super("RMI 채팅");

            Container c = getContentPane();
            c.setLayout(new BorderLayout());

            display = new JTextArea();
            display.setEditable(false);
            JScrollPane spane = new JScrollPane(display);
            c.add(spane, "Center");

            npanel = new JPanel();
            card = new CardLayout();
            npanel.setLayout(card);

            label = new JLabel("대화명 : ");
            id = new JTextField(10);
            register = new JButton("등록");
            register.addActionListener(this);
            close = new JButton("종료");
            close.addActionListener(this);
            JPanel loginPanel = new JPanel();
           
            loginPanel.add(label);
            loginPanel.add(id);
            loginPanel.add(register);
            loginPanel.add(close);


            nick = new JLabel("즐팅!!");
            input = new JTextField(10);
            input.addActionListener(this);
            enter = new JButton("입력");
            enter.addActionListener(this);
            clear = new JButton("지우기");
            clear.addActionListener(this);
            JPanel chatPanel = new JPanel();

            chatPanel.add(nick);
            chatPanel.add(input);
            chatPanel.add(enter);
            chatPanel.add(clear);

            npanel.add(loginPanel, "login");
            npanel.add(chatPanel, "chat");
            c.add(npanel, "North");

            card.show(npanel, "login");   

            addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    setVisible(false);
                    if ( server != null ) {
                        try {
                            server.unregister(ClientImpl.this, name);
                        } catch ( Exception ee ) {
                            ee.printStackTrace();
                        }
                    }
                    dispose();
                    System.exit(0);
                }
            });
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setSize(400,500);
            setVisible(true);
        }
       
        private void connect(){
            try {
                UnicastRemoteObject.exportObject(this);
                server = (Server)Naming.lookup("rmi://61.103.103.184/chat");
                server.register(this, name);
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
       
        public synchronized void back(String msg){
            try {
                display.append(msg + "\n");
            } catch (Exception e) {
                display.append(e.toString());
            }
        }
       
        public void actionPerformed(ActionEvent e){
            Object o = e.getSource();

            if ( o == register ) {
                name = id.getText().trim();
                card.next(npanel);
                connect();
                nick.setText(name+"님, 즐팅!!");
            } else if ( o == input || o == enter ) {
                try {
                    server.send(name + " : " + input.getText());
                    input.setText("");
                } catch ( Exception ex ) {
                    display.append(ex.toString());   
                }
            } else if ( o == clear ) {
                display.setText("");
            } else if ( o == close ) {
                System.exit(0);
            }

        }
       
        public static void main(String[] args)     {
            new ClientImpl();
        }
    }

첫 실행화면

ClientImplNickInput.JPG

대화명 입력 후 화면

ClientImplNickInputAfter.JPG

다른이가 입장하였을 경우의 화면

OtherUserEnter.JPG

유저가 퇴장하였을 때 화면

OtherUserGetOut.JPG  

이 글은 스프링노트에서 작성되었습니다.

출처 : http://www.javastudy.co.kr/docs/lec_corba/rmi2.html

Java RMI (Remote Method Invocation)



Abstract:
기존의 자바 소켓(Socket) 으로 대부분의 통신 프로그래밍이 가능했으나 분산되어 있는 객체간의 메시지 교환을 위해서는 프로그래머가 일일이 응용레벨 프로토콜을 직접 설계 해야 하며 이는 복잡하고 애러를 발생시키는 주된 요인이 되기도 한다. 이러한 소겟 프로그래밍을 대체 할수 있는 것이 원격메소드호출 (Remote Mothod Invocation)이며, RMI 는 분산된 객체들을 local 객체처럼 사용이 가능하다. 본 강의는 RMI 의 개념과, 프로그래밍 방법등을 예제를 통해 설명한다.
Keywords:
java, rmi, network

1.서론

인터넷과 인트라넷 제품을 위한 디자인은 항상 객체의 전달에 관한 문제에 직면하게 되며 대부분은 라인 프로토콜의 자체 개발로 많은 시간과 비용이 소요되었다. 특히 이러한 작업은 복잡하고 애러를 발생시키는 주된 요인으로 작용한다. Java RMI 는 이러한 문제들을 해결할수 있는 해결사로서 네트워상에서 객체의 전달을 투명하게 한다. 다시말해 Java RMI (Remote Method Invocation)은 분산된 객체를 마치 로컬에 있는 객체를 다루듯이 사용할수 있으며 기존의 소켓 프로그래밍과 같은 복잡한 설계 절차와 애러를 발생시키는 요인을 극소화 시켰다. 모든 네트웍 프로그래밍의 자세한 부분, 즉 소켓 API 를 사용해서 구현되는 부분은 RMI package, client stub 그리고 server stub에 의해 숨겨진다.
원격절차호출 RPC(Remote Procedure Call)와는 달리 RMI 는 Java VM 환경에서 실행되므로 XDR(eXternal Data Representation) 과 같이 다른 시스템간에 이식 가능한 형태로 데이타를 코드화는 표준 방법을 필요로하지 않는다.

2. RMI 의 개발 목적.

* 안정된 원격 호출의 제공.
* 서버에서 애플랫으로의 콜백 제공.
* 분산모델을 자바환경으로의 통합.
* 분산 객체와 비분산 객체의 명확한 구분.
* 안정된 분산 애플리케이션을 간편하게 만들수 있는 환경제공.
* 자바 런타임환경에의해 제공되는 안전성 유지.

3.자바 분산 객체 모델

image2.gif

JAVA RMI Architecture

3.1. 용어 정리.

*원격 객체(remote object)
다른 호스트에 있는 자바 VM 으로부터 호출되어지는 메소드를 가지고 있는 객체.
*원격 인터페이스(remote interfaces)
원격 객체의 메소드를 선언하는 자바 인터페이스.
*원격 메소드 호출(Remote Method Invocation)
원격 인터페이스 안에 정의된 리모트 객체의 메소드를 호출하는 것.

3.2. 분산 모델과 비분산 모델의 차이점.

  1. 원격 객체의 클라이언트들은 구현 클래스들과 상호작용을 하는 것이 아니라 원격 인터페이스와 상호작용을 한다.
  2. 원격메소드 호출시 (원격이 아닌) 독립 변수나 결과값들은 참조가 아닌 복사로서 전달이 된다.
  3. 원격 객체는 원격구현이 복사가 되는 것이 아니라 참조값으로 값이 전달된다.
  4. 지역 객체 호출보다 원격 객체 호출시 오류가 발생할 확율이 높으므로 클라이언트는 추가로 예외를 처리할수 있어야 한다.

3.3. RMI 의 Interface 와 Class.

java.rmi 안에 정의 되어 있는 인터페이스들과 클래스들은 RMI System 의 상태(behavior)들을 기술하고 있다. 밑의 그림은 인터페이스들과 클래스들간의 관계를 나타낸 것이다.

3.3.1 Remote Interface.

모든 Remote Interface 는 java.rmi.remote 를 상속 받는다.

public interface Hello extends java.rmi.Remote {
String sayHello() throws java.rmi.RemoteException;
}

몇가지 주의할 점은 다음과 같다.

  • 각 메소드는 반드시 java.rmi.RemoteException 으로 예외 처리를 해주어야 한다.
  • 독립변수나 리턴값으로 넘겨지는 remote object 는 interface 에 정의된 메소드를 구현한 클래스(implementation class) 로 선언하지 말고 remote interface 로 선언해야 한다.

3.3.2 RemoteException Class

java.rmi.RemoteException 클래스는 RMI 실행시간에 발생할수 있는 예외들의 슈퍼클래스 이다. RMI 시스템을 사용하는 애플리케이션의 견고성을 보장하기 위해서는 remote interface 에 선언된 각각의 메소드에 예외처리를 해주어야 한다. java.rmi.RemoteException 은 메소드 호출의 실패, 네트웍크의 고장 또는 서버에 문제가 생겼을경우 발생한다.

3.3.3 RemoteObject Class 와 슈퍼클래스.

RMI 서버 function 은 java.rmi.server.RemoteObject 와 그 subclass 인 java.rmi.server.UnicastRemoteObject 에 의해 제공된다.
  • java.rmi.server.RemoteObject 클래스는 remote object 에 사용될수 있는 hashCode, equals, toString 를 제공한다.
  • object 를 생성하고 원격으로 사용할수 있도록 하는 .function 은 java.rmi.server.RemoteServer 와 그 subclass 에 의해 추상적으로 제공된다.
  • java.rmi.server.UnicastRemoteObject 클래스는 unicast remote 객체를 정의한다. 이 객체는 서버 프로세서가 살아있을 경우에 참조가 가능하다.

3.4.4 Implementing a Remote Interface

remote interface 를 구현(implemetation) 하기 위한 일반적인 방법은 다음과 같다.
  • 구현하는 클래스는 주로 java.rmi.server.UnicastRemoteObject를 상속받으며 아울러 UnicastRemoteObject 의 상위 클래스인 java.rmi.server.RemoteObject와 java.rmi.server.RemoteServer 의 상태를 상속 받는다.
  • 여러개의 remote interface를 구현할수 있다.
  • 다른 원격 구현(remote implementation) 클래스를 상속받을수 있다.
  • remote interface 에 선언되지 않은 method 를 정의할수는 있으나 그 메소드는 단지 지역(local)에서만 사용이 가능하고 원격으로는 쓰일수 없다.

    import java.rmi.*;
    import java.rmi.server.UnicastRemoteObject;
    public class HelloImpl extends UnicastRemoteObject implements Hello
    {
    public String sayHello() throws RemoteException
    {
    ......
    }
    }

3.4.5 원격 객체의 type = 지역 Stub의 type

분산 객체 모델에서 client 는 원격 객체의 클래스에 의해 구현되는 원격 인터페이스의 집합을 가지는 stub 객체와 상호 작용을 한다. stub 클래스는 원격 객체가 아닌 보통 클래스는 포함하지 않는다. 클래스 계층구조에서 만약 C가 B로부터 상속받고 B는 A로부터 상속을 받는다고 가정하자. 그리고 단지 B만이 원격 인터페이스를 구현한다면 stub는 단지 B로부터 생성되지 C로부터는 생성이되지 않는다. Stub 는 하나의 원격 객체로 원격 인터페이스의 집합을 구현하므로 자바시스템의 관점에서는 원격객체와 같은 형을 가지고 있다고 보는것디다. 따라서 클라이언트는 내장된 자바 연산으로 원격객체의 형을 채크할수 있으며 또한 임의의 원격 인터페이스를 다른 원격 인터페이스로 캐스트 할수 있다.

3.4.6 인자(parameter)의 전달

 

원격 객체로부터 주고 받는 인자는 serializable 한 java형이면 모두 가능하다. 이것은 원시적(primitive) 형을 포함하여 원격 java 객체와 java.io.serializabe 을 구현한 원격이아닌 java 객체를 포함한다. Serializable 에 관한 자세한 정보는 (Reference)의 "Object Serialization Specification" 을 참조하기 바란다. 애플랫의 경우 인자로 쓰이는 클래스나 또는 리턴값이 지역에서 유효하지 않을 경우 AppletClassLoader 를 통해 동적으로 로드된다.애플리케이션의 경우 이러한 클래스들은 디폴트로 class loader또는 RMIClassLoader에 의해 불리워 진다.
보통 객체로서의 인자 전달.
원격메소드호출에서 인자로서 또는 결과값으로 넘겨지는 보통객체는 복사로서 전달된다. 다시말해 RMI 에 의해 불리워진 메소드가 보통객체의 메소드일경우 먼저 원격지로부터 복사가되어 지역으로 옮겨진후에 그 객체의 메소드가 실행이되는 것이다.
원격객체로서의 인자전달.
원격객체를 인수로 넘길경우 원격객체의 stub 가 전달된다.

3.4.7 예외 핸들링.

원격메소드에 java.rmi.RemoteException 처리를 해주므로 호출을 하는 쪽에서는 반드시 이 예외를 다룰수 있도록 준비를 해야한다. 원격호출을 하는동안 java.rmi.RemoteException이 발생하면 클라이언트는 호출중에 일어난것인지 그 후에 일어난 것인지 아니면 그 전에 일어난것ㅇ인지에 대한 정보가 거의 없다. 따라서 원격 인터페이스와 그 안에 선언된 메소드들은 이러한 상황을 염두해두고 설계되어야한다.

3.4.8 RemoteObject 클래스에의해 override 되는 메소드.

Object 클래스 안에는 equals, hashCode, toString 메소드가 구현되어 있다. 하지만 이들은 원격객체를 위한것이 아니다. 따라서 jaa.rmi.server.RemoteObject 클래스는 이 메소드들을 원격 객체에 알맞게 override 했다.

3.4.9 final 로 선언된 객체.

getClass, notify, notifyAll, wait 메소드들은 Object 클래스에서 final 로 정의되어 있어 override 되어질수 없다.

3.4.10 원격 객체의 위치.

 

원격 객체의 참조는 java.rmi.Naming 클래스의 URL 관련 메소드에의해 가능하다. 클라이언트가 원격 객체를 호출하기 위해서는 먼저 그 객체에 대한 참조 정보를 얻어야만한다. 보통 원격 객체의 참조는 메소드 호출에 의해 리턴되는 값으로부터 얻어진다. RMI 시스템은 간단한 bootstrap 네임서버를 제공한다. 이를통해 주어진 호스트의 리모트 객체를 얻을수 있다. java.rmi.Naming 클래스는 lookup, bind, rebind, unbind, list 와 같은 URL-based 메소드를 제공한다.

4. RMI 시스템의 구조

RMI 시스템은 stub/skeleton 래이어, remote reference 래이어, transport 래이어로 구성되어 있으며 각 래이어의 경계는 특별한 인터페이스와 프로토콜에 의해 정의되진다. 또한 각 래이어는 서로 독립적이며 따라서 다른 래이어에 영향을 주지 않고 한 래이어의 성질을 바꿀수 있다. 예들들어 설명하자면, 현재 transport 구현은 TCP를 바탕으로 하고 있으나 다른 래이어에 영향을 주지 않고 UDP 를 바탕으로한 transport 로의 교체가 가능한 것이다.
어떠한 주소공간에서 다른 주소공간으로 객체의 전달을 투명하게 하기 위해서는 자바를 위해 특별히 제작된 Object serialization 기술이 쓰인다. 자세한 내용은 "Object Serialization Specification"을 참조하라.
또 다른 테크닉으로 Dynamic stub loading 이 있다. 이는 remote interface를 구현하는 client-side stub 를 지원하기 위해 쓰인다. 예들들면 정확한 형의 stub 가 클라이언트에서 유효하지 않을경우 클라이언트가 자바에 내장된 연산자를 캐스팅과 타입채킹에 사용하도록 허용한다. 그림 생략
  1. stub/skeleton
    클라이언트가 remote server의 객체를 호출할때 실재로 호출되는 부분으로 stub는 원 격 인터페이스의 구현으로 호출 요청을 remote reference layer를 통해 서버 객체로 보내는 역할을 담당한다. skeleton 은 그 반대로 생각하면 되겠다.
  2. remote reference layer
    호출 정보를 분석해서 server 가 단일 객체인지 아니면 여러 사이트에 흩어져 있는 복수개의 객체인지를 판별후 호출을 실행한다. 또한 그 서버가 항상 실행상태인지 아니면 호출시에만 실행이되는지에 따른 참조방법을 추상화 한다. 따라서 상위 래이어에서는 이러한 차이점이 보이지 않게 된다.
  3. transport layer
    연결 setup, 연결 관리, 그리고 연결 감시등을 책임지는 래이어다.
    각 래이어의 경계는 특별한 인터페이스와 프로토콜에 의해 정의되지며 각 래이어는 서로 독립적이며 따라서 다른 래이어에 영향을 주지 않고 한 래이어의 성질을 바꿀수 있다. 예들들어 설명하자면, 현재 transport 구현은 TCP를 바탕으로 하고 있으나 다른 래이어에 영향을 주지 않고 UDP 를 바탕으로한 transport 로의 교체가 가능한 것이다.

5. Resource

다음은 Java RMI 관련 자료들이 있는곳이다. 기본적인 프로그래밍과 소스코드 그리고 Socket Programming 과 RMI 를 사용한 Performance 평가등이 있으니 직접 접속해 유용한 정보를 얻을수 있기를 바란다.
  • JavaSoft (http://chatsubo.javasoft.com/)
    RMI specification, Object Serialization 그리고 RMI 를 처음 접하는 프로그래머를 위한 기본 프로그래밍 예제 "Getting start with RMI"를 제공하며 RMI 관련 Project 를 수행하는 회사와 제품에 대한 정보를 얻을수 있다.
  • rmi-users mail achive (http://chatsubo.javasoft.com/email/rmi-users)
    RMI 에 관심이 있는 사람들의 메일을 모아놓은 곳이다. 초급부터 고급까지 다양한 질문과 답변들이 있다. 프로그래밍을 하면서 궁금한 점이 있으면 메일링 리스트에 가입을 하거나, 또는 achive 를 참조한다면 많은 도움이 될 것이다.
  • Game Client/Server (http://www.digitalfocus.com/ddj/code/)
    RMI 를 이용한 간단한 Client/Server 프로그램이다. 네트웍을 이용한 게임도 RMI 를 이용하면 충분히 큰 효과를 얻을것으로 생각된다.
  • Client/Server Computing using JDBC & RMI (http://www.geocities.com/SiliconVally/Park/9841/rmi.html)
    RMI는 CGI 와 비교하여 성능의 향상과 함께 데이타베이스와의 persistent한 연결이 가능며, 서버의 처리능려과 로컬의 처리능력을 결합함으로서 자원의 요구를 최소화 시킬수 있다. JDBC 프로그래밍에서 Socket & JDBC, RMI & JDBC 까지 상세한 해설과 코드를 제공한다.

6. Hello World

본문의 예제를 논하기 앞서 먼저 준비해야할 일이 있다. 밑의 내용을 참조하여 자신이 필요한 것이 무엇인지 판단하고 RMI 를 실행할수 있는 환경을 구축해야 한다.
Client                          Java VM         Install
Windows 95/NT Netscape 3.01 1.0.x Netscape plug-in
Windows 95/NT HotJava 1.0 1.1 No installation required
Windows 95/NT appletviewer 1.1 No installation required
1.1.1
Solaris Netscape 3.0.1 1.0.x Install RMI libraries for 1.02
Solaris HotJava 1.1 1.1 No installation required
Solaris appletviewer 1.1.1 1.1 No installation required

시작하기전에 먼저 작업할 디렉토리를 정한다. 본문의 예제는 jdk1.1.1/mysrc/examples/hello 로 한다.
디렉토리가 없으면 다음과 같이 디렉토리를 만든다.

mkdir $HOME/java/mysrc/examples/hello

1. Remote Interface 정의.

Remote method invocation 은 여러가지 이유로 인해 실패할 가능성이 있다. 주된 이유는 네트웩크에 관련된 문제 또는 서버의 문제등을 들수 있다. 이러한 문제는 remote object 사용시 반드시 고려되어야 한다. remote object 라는것을 알리기 위해서 object 는 remote interface 를 구현(implement)해야 한다. 따라서 먼저 remote interface 를 선언한다.
인터페이스는 반드시 public 으로 선언하고 java.rmi.Remote 를 상속받는다. 또한 인터페이스 안에 선언된 메소드는 java.rmi.RemoteException 처리를 해주어야 한다.

-- Hello.java --
package examples.hello;
public interface Hello extends java.rmi.Remote { String sayHello() throws java.rmi.RemoteException; }

2. Implementation Class (remote object)

HelloImpl.java 코드는 Hello World 서버의 역할을 한다.

-- HelloImpl.java --
import java.rmi.*; import java.rmi.server.UnicastRemoteObject;
// 구현되는 인터페이스를 기술한다.// public class HelloImpl extends UnicastRemoteObject implemnents Hello{ private String name;
// 원격 객체의 생성자를 정의한다. //
public HelloImpl (String s) throws RemoteException { super(); name = s; }
// 인터페이스에 선언된 메소드를 구현한다. //
public String sayHello() throws RemoteException { return "Hello World!"; }
public static void main(String args[]) { System.setSecurityManager(new RMISecurityManager()); try { HelloImpl obj = new HelloImpl("HelloServer"); // 원격 객체를 등록시킨다. // Naming.rebind("//sarang.kyungsung.ac.kr/HelloServer",obj); System.out.println("HelloServer bound in registry"); } catch (Exception e) { System.out.println("HelloImpl err: " + e.getMessage()); e.printStackTrace(); } } }

3. Remote 서비스를 이용하는 Applet

Hello World 예제의 부분인 애플랫은 HelloServer 의 sayHello 메소드를 호출한다. 그결과로 "Hello World!" 를 화면에 표시한다.

-- HelloApplet.java --
package examples.hello;
import java.awt.*;
import java.rmi.*;
public class HelloApplet extends java.applet.Applet { String message = ""; public void init() { try { Hello obj = (Hello)Naming.lookup("//" + getCodeBase().getHost() + "/HelloServer"); message = obj.sayHello(); } catch (Exception e) { System.out.println("HelloApplet exception: " + e.getMessage()); e.printStackTrace(); }
}
public void paint(Graphics g) { g.drawString(message, 25, 50); }
}

4. HTML 작성.

<HTML> 
<title>Hello RMI</titlt>
<center> <h1>Hello RMI</h1> </center>
The message from the HelloServer is:
<p> <applet codebase="../.." code="examples.hello.HelloApplet" width=500 height=120>
</applet>
</HTML>

$HOME/jdk1.1.1/mysrc/hello 안에는 다음의 4가지 file 있다.

Hello.java - remote interface.HelloImpl.java - remote object (Applet 의 서버)HelloApplet.java - Applet 소스 코드.index.html - Web page.

* Compile

javac -d /$HOME/public_html/codebase *.java

* Stub 와 Skeletons 생성.

rmic -d $/HOME/public_html/codebase examples.hello.HelloImpl
위 명령을 실행한후에 다음 2개의 클래스 파일이 생성된다.
HelloImpl_Stub.class
HelloImpl_Skel.class

* move HTML file

mv $HOME/java/mysrc/examples/hello/index.html
$HOME/public_html/codebase/examples/hello

* Start

start rmiregistry (Win 95)
rmiregistry & (Solaris)
디폴트로 1099 포트를 사용하나 다른 애플리케이션이 사용중이라면 rmiregistry 2002 & 처럼 1099외의 포트를 사용한다.
java -Djava.rmi.server.codebase=http://sarang.kyungsung.ac.kr/~yjmoon/codebase/
examples.hello.HelloImpl &
appletviewer http://sarang.kyungsung.ac.kr/~yjmoon/codebase/examples/hello/index.html &

Reference

[1] JavaSoft, Information on configuring the RMI plug-in:

http://chatsubo.javasoft.com/current/doc/rmi/release-notes.html

[2] JavaSoft, The complete Object Serialization Specification:

http://chatsubo.javasoft.com/current/doc/serial-spec/serialTOC.doc.html

[3] JavaSoft, Getting Started Using RMI:

http://chatsubo.javasoft.com/current/doc/tutorial/getstart.doc.html

[4] JavaSoft, Java Remote Method Invocation Specification:

http://www.javasoft.com:80/products/jdk/1.1/docs/guide/rmi/spec

[5] JavaSoft, Java Remote Method Invocation API:

http://www.javasoft.com:80/products/jdk/1.1/docs/api

 

이 글은 스프링노트에서 작성되었습니다.

DBany2009.jpg

압축파일을 원하는 곳에 압축을 풀고나서 확인해보면 DBany.exe 라고 하는 실행파일이 있다. 이것을 실행시켜준다.

DBany2009Begin.jpg

 

그럼 다음과 같은 창이 뜨면 정상적으로 실행이 된것이다. 신규를 눌러서 Oracle DB 정보에 맞추어서  입력해준 후 저장을 누른다.

설정방법이 어려우면 <<< 여기 링크를 눌러서 확인 >> 하기 바랍니다.

DBany2009SqlLogin.jpg

그후 새로 연결을 누르면

DBany2009Starting.jpg

그러면 다음과 같은 화면이 나온다. 로그인은 완료된 것이다. ㅡㅅ-)b

 

이후 사용방법은... 알아서 체득하시길... ^+_+)> 다 알려주면 재미없지 않은가? ㅎㅎ

 

간단한 팁이라면...

 엑셀에서 칼럼 수와 속성에 맞추어 값을 입력한 후에, 97-2003 버전으로 저장하고 나서 이것을 불러와 입력할 수도 있다.

다만, 오라클의 제약조건을 위반하는 항목이 발생할 경우 거기서 멈추므로 사전에 확인을 하시기 바란다. ㅡㅅ-)b


보시는 것처럼 엑셀로 입력작업을 해줍니다.

저장형식은 보시는 것처럼 97-2003 버전으로 해주십시오.

DBany 에서 불러오기 하려는 레코드 에서 마우스 우클릭 후 엑셀화일 읽기를 누릅니다.

엑셀버전을 선택하고, 읽을 화일명 옆에 있는 화일 버튼을 클릭합니다.

원하는 엑셀파일을 불러오면 미리보기에서 확인이 가능합니다.

파일이 맞으면, 화일 읽기 범위 선택에서 원하는 범위를 선택하고 처리 시작을 누르면 됩니다.

그럼 아래처럼 쭈욱 입력이 됩니다. ㅡㅅ-)b 참 쉽죠잉?? DB연결에서 No AutoCommit; 에 체크하신 분은 별도로 commit; 처리를 해주셔야 합니다. 위의 도구창에서 세션-> 에 보시면 rollback 혹은 commit 버튼 있으니까 취향에 따라서 선택하십시오. ^^


 

이 글은 스프링노트에서 작성되었습니다.

홈페이지 링크 : http://www.dbany.com/

현재는 2009버전까지 나온 상태입니다. 박희성님이 하사해주시고 계십니다. ㅠㅅ-) 비영리목적으로 마음껏 쓸 수 있다니 얼마나 좋습니까!!

우선은 회원가입을 하셔야 합니다. ^^ 무료로 사용하기 위해 간단한 내용 기재는 필요하지 않을까요? ^^


DBany2009License.JPG

 

DBany2009upgrade.JPG 

공지사항에 가시면 4번째 에러 패치... 라는 내용의 글이 있습니다. 거기에 첨부되어 있는 DBAny_2009_20090203Up.zip을 다운 받으시면 됩니다.

별도의 설치 프로그램이 없으므로 압축을 원하는 폴더에 푸신 다음에 안에 첨부되어 있는 DBANY.exe를 실행하시면 됩니다.

 

DBany2009.JPG

 

무료 오라클 관리툴 : DBany2009 사용방법

 

이 글은 스프링노트에서 작성되었습니다.

관련내용 페이지 : http://cafe.naver.com/tonkjsp/150

 DBA_Master2000 간단한 활용법

    ① Table Manager 기능


         ㉠ Table Manager 실행시키기

           Table → Table Manager (도구모음에서  아래 그림에서 가리키는 아이콘을 클릭하면 됨)

         
         
         
      
       ㉡ 테이블 매니저에서 테이블 관리하기

          - 로그인 한 계정의 테이블 수

         

          
          -  현재 접속된 사용자 계정명,  선택된 테이블명, 테이블 리스트,  선택되어진 테이블의 데이터들(필드들)
         
         

        
          - 테이블 리스트 다시 불러 오기, 테이블 명세서 출력,  테이블 (목록, 데이터, 인덱스,  인덱스 필드, 컬럼,  제약조건, 제약
            조건 필드 트리거) 엑셀 파일 혹은 HTTP 테이블로 저장하기
           
            테이블 리스트 다시 불러오기 - 윈도우에서 새로고침(F5) 같은 의미 같네요

           

            테이블 명세서(가로, 세로) 출력하기 혹은  테이블 속성정의서 출력(가로/세로)


            (제 생각이지만 명세서 출력이 엑셀로 바로 출력되었다면 웹사이트 개발자가 좀더 편리해지지 않을까 싶네요)
           
             - 편법이지만 DBA_Master2000에서 Microsoft Office Document Image Writer 이것을 지원하기에 MDI 파일 형식으로
             출력하고 MDI에서 MS-WORD로 출력 할 수 있는 기능이 별도로 존재하더라고요 그러면 MS-WORD =>MS-EXCEL
             로 변환하면 될 것 같습니다. 하지만 약간의 편집은 해야 할 것 같더라고요. 그래도 타이핑으로 일일이 보고 하는 것
             보다는 낳은 것 같네요

              Dept 테이블에 대한 명세서를 한번 출력시켜 보도록 하겠습니다.
                  
            
            
             Print Preview로 출력하기 전에 미리 볼 수 있는 창이 나옵니다. Printer Setup 로 출력할 방식을 설정하겠습니다.
             (MDI 파일형식을 선택하겠습니다. - 기본값)

            
            
            
            
             MDI 파일로 저장하기 (프리터 모양의 아이콘을 클릭하여 적당한 경로 파일을 저장한다.)
             
                      

    
              MDI 파일을 실행시킨다. (MDI 파일을 실행시킬 수 있는 프로그램 깔려 있다면 바로 실행이 됩니다.)
              도구 → Word로 텍스트 보내기 혹은 도구모음에서 아래 그림과 같이 해당 아이콘을 클릭합니다.
              MS-Word로 변환하면 완벽하게 출력이 되지 않네요. (그럭저럭 쓸만 한데,, 좀 아쉽지만 말이죠)

            
              
             - 테이블 (목록, 데이터, 인덱스,  인덱스 필드, 컬럼,  제약조건, 제약 조건 필드 트리거) 엑셀 파일 혹은 HTTP 테이블로
             저장하기
                               
               

 
            - 테이블 생성 및 트리거 스트립트 조회

 

              테이블 이름 변경  : 테이블 리스트에서 마우스 오른쪽 버튼을 눌러 테이블 이름 변경을 클릭한다.

             

             

 

              테이블명을 변경하기 위한 설정 창이 나옵니다. (테이블명을 변경하시면 됩니다.)

             

            

 

              테이블 생성 ☞ 이건 되지 않네요

             

                    

 

              테이블 스트립트 조회 :

              

            


            - 테이블 삭제, 테이블 데이터 일괄 삭제 : 테이블 리스트에서 마우스 오른쪽 버튼을 클릭한다.

            ※ 테이블 삭제는 테이블과 테이블안에 있는 데이터 모두 삭제하는 것입니다.

                테이블 데이터 일괄 삭제는 테이블은 그대로 있고 해당 테이블 안에 있는 데이터만 삭제 하는 것입니다.

 

            


       ㉢  데이터재조회, 추가, 수정, 삭제, 엑셀로저장, 엑셀화일 읽기, 출력
         
           -  데이터 재조회

          
          
           -  데이터 추가   :  필드 목록이 출력된  곳에서 마우스 오른쪽 버튼을 누르면 레코드 추가가 나오는데 이걸 클릭하면
           데이터를 추가할 수 있게 필드 목록 리스트에 나옵니다. 데이터를 입력하고 데이터베이스 저장를 클릭하면 끝납
           니다.
          
         
          


           

          
          재조회를 눌러 정확하게 Oracle DB Server 데이터 저장되었는지 확인한다.
        
         

  
          -  데이터 수정

        

 

         수정결과 확인

 

        


          -  데이터 삭제
        

         

 

          혹은 바로가기 실행 메뉴에 데이터 레코드 삭제를 이용하여 삭제하는 경우도 가능하다.

          바로가기 실행 메뉴는 해당 테이블 데이터에서 오르쪽 마우스를 클릭하면 나옵니다 

 

         


          -  엑셀파일로 저장
          테이블에 필드 데이터를 MS-Excel 파일로 저장하는 방법으로

          바로가기 실행 메뉴는 해당 테이블 데이터에서 오르쪽 마우스를 클릭하면 나옵니다. 여기서 화일저장 클릭하면 된다.

 

        

 

         화일을 저장하기 위한 설정 창이 나옵니다.

 

        


       -  엑셀파일 읽어 오기 
       테이블에 엑셀 파일로 작업된 데이터를 읽혀 들여 DB 에 저장하는 방법입니다.

       바로가기 실행 메뉴는 해당 테이블 데이터에서 오르쪽 마우스를 클릭하면 나옵니다. 여기서 엑셀화일 읽기 클릭하면 된다.

 

          

 

       아래와 같이 임시로 엑셀파일을 하나 만들도록 하겠습니다.

 

           

 

      엑셀파일을 읽어오기 위한 설정 창이 나옵니다.

 

     

      

      ※ 참고로 임시로 만든 엑셀파일인 경우 데이터 시작점은 2 가 됩니다.

 

       


       - 테이블 필드속성 조회 -> 칼럼명,타입,길이,설명입력/조회등
      

       


       - 인덱스정보, 제약조건 정보, 트리거정보, 테이블 생성정보


        인덱스 정보

 

      

 

       제약조건 정보

 

      

 

       트리거 정보

 

       

 

       테이블 정보

 

      


   ② Session Manager

      - 이부분은 써보지 않아서 잘 모르겠네요

 

   ③ Storage Manager

      - 이부분은 써보지 않아서 잘 모르겠네요

 

   ④ Security Manager

      - 이부분은 써보지 않아서 잘 모르겠네요 

 

   ⑤ SQL Script 와 Oracle SQL*Plus

 

     - SQL*Plus가 연결이 되지 않는다. (DBAMaster2000에서 연결이 잘 되지 않는 것 같아요, DBany/2009 에서는 연결 됨) 

     - SQL Script : 쿼리 문을 좀 더 편리하게 사용할 수 있게 해둔 기능 같아요

       (기본적인 SQL문으로 쿼리 문을 생성하고 그결과를 바로 확인 가능합니다.)

 

        SQL Script 실행하기

       

       

 

        또 다른 방법은 Query 메뉴 밑에 SQL Script 선택하면 된다.

        
       

       

        아래 부분 탬 메뉴 중에 SQL문 생성 선택합니다.

        SQL 탬은 기본적인 SQL 문 있어서 DML, DCL, DDL 작업하기 좀 더 효율적인거 같네요

        함수 탬은 SQL 함수에 대한 리스트가  나옵니다. (SUM, COUNT, AVG,, MAX, MIN 기타 등등 )

        연산자 탬은 쿼리 문 조회때 연산자 입력시 사용합니다.(and , is null 등등 )

        예약어 탬은 SQL 쿼리문 사용시 정해져 있는 단어들의 집합이네요

 

       


+ Recent posts