Aplikacje biznesowe Wykład dla studentów Informatyki Stosowanej UJ 2006/2007 Michał Cieśla pok. 440a, email: ciesla@if.uj.edu.pl konsultacje: wtorki 10-12 http://users.uj.edu.pl/~ciesla/ 1
2 Plan wykładu 1. Serwer aplikacji (JBoss) 2. J2EE i Enterprise JavaBeans (EJB) 3. Wzorce projektowe.
3 Literatura 1. B. Burke, R. Monson-Haefel Enterprise JavaBeans, 3.0, Helion 2006 2. E. Roman, S. W. Ambler, T. Jewell Enterprise JavaBeans, Helion 2003 (Mastering Enterprise JavaBeans, 2 nd Edition) 3. W. Crawford, J. Kaplan J2EE. Stosowanie wzorców projektowych, Helion 2004 (J2EE Design Patterns). 4. D. Aldur, J. Crupi, D. Malks J2EE wzorce projektowe, Helion 2004 (Core J2EE Patterns: Best Practices and Design Strategies, 2 nd Edition). 5. http://java.sun.com 6. http://www.google.pl
Java Management Extensions 1. Wprowadzenie do JMX 2. Podstawy JMX Standard MBean. powiadomienia, MXBean, deskryptory. 3. JMX i RMI 4. Dynamic MBean Źródło: http://java.sun.com/javase/6/docs/technotes/guides/jmx/overview/jmxoverviewtoc.html http://java.sun.com/javase/6/docs/technotes/guides/jmx/tutorial/tutorialtoc.html 4
5 Java Management Extensions JMX określa architekturę, wzorce projektowe, API oraz usługi zarządzania i monitorowania dla języka Java. Zasoby są sterowane poprzez obiekty zwane Managed Beans lub MBeans, zarejestrowane na serwerze MBean'ów. Specyfikacja określa także agenta JMX. Składa się on z serwera MBean'ów oraz zbioru usług umożliwiających operację na MBean'ach. W ten sposób agent bezpośrednio kontroluje zasoby i udostępnia je dla zdalnych aplikacji sterujących.
Java Management Extensions Zalety JMX: dostępność aplikacje mogą być zarządzane poprzez większość urządzeń udostępniających Javę, standaryzacja oprogramowanie zgodne z JMX mogą być zarządzane w jednolity sposób (np. serwery aplikacji J2EE), skalowalność każda usługa to niezależny moduł, wszechstronność usługi mogą korzystać ze wszystkich technologii wytworzonych w ramach języka Java, uniwersalność i otwartość agenci JMX mogą być sterowani w różny sposób np: poprzez przeglądarkę www. Ponadto każdy może opracować własne rozwiązania oparte na JMX. 6
Standard MBean Standardowy MBean tworzy się pisząc interfejs JakisMBean oraz klasę Jakis implementującą ten interfejs. Każda metoda w interfejsie określa atrybut lub operację (domyślnie). package com.example.mbeans; public interface HelloMBean { // operacje public void sayhello(); public int add(int x, int y); // attrybuty // read-only public String getname(); // read-write public int getcachesize(); public void setcachesize(int size); 7
package com.example.mbeans; Standard MBean - implementacja public class Hello implements HelloMBean { public void sayhello() { System.out.println("hello, world"); public int add(int x, int y) { return x + y; public String getname() { return this.name; public int getcachesize() { return this.cachesize; public synchronized void setcachesize(int size) { int oldsize = this.cachesize; this.cachesize = size; System.out.println("Cache size now " + this.cachesize); private final String name = "Reginald"; private int cachesize = DEFAULT_CACHE_SIZE; private static final int DEFAULT_CACHE_SIZE = 200; 8
// Stworzenie ObjectName dla MBean'a ObjectName name = new ObjectName( "com.example.mbeans:type=hello"); // Utworzenie MBean'a Hello mbean = new Hello(); // Rejestracja MBean'a mbs.registermbean(mbean, name); // Oczekiwanie System.out.println("Waiting forever..."); Thread.sleep(Long.MAX_VALUE); 9 Standard MBean - agent JMX package com.example.mbeans; import java.lang.management.*; import javax.management.*; public class Main { public static void main(string[] args) throws Exception { // Odebranie Serwera MBean'ow MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
10 Standard MBean - zarządzanie kompilacja, $ javac com/example/mbeans/*.java uruchomienie agenta, $ java com.example.mbeans.main uruchomienie Java Monitoring and Management Console, $ jconsole wybranie z listy com.example.mbeans.main i nawiązanie połączenia.
11 Powiadomienia MBean może wysyłać powiadomienia aby przykładowo poinformować o zmianie stanu, zajściu zdarzenia czy też problemie. Aby wygenerować powiadomienie należy zaimplementować interfejs NotificationBroadcaster lub podinterfejs NotificationEmitter. Każde powiadomienie posiada źródło oraz numer, który może być użyte do szeregowania powiadomień.
12 Powiadomienia... public class Hello extends NotificationBroadcasterSupport implements HelloMBean {... public synchronized void setcachesize(int size) {... // Utworzenie powiadomienia Notification n = new AttributeChangeNotification(this, sequencenumber++, System.currentTimeMillis(), "CacheSize changed", "CacheSize", "int", oldsize, this.cachesize); // Wysłanie powiadomienia sendnotification(n);
13 Powiadomienia @Override public MBeanNotificationInfo[] getnotificationinfo() { String[] types = new String[] { AttributeChangeNotification.ATTRIBUTE_CHANGE ; String name = AttributeChangeNotification.class.getName(); String description = "An attribute of this MBean has changed"; MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description); return new MBeanNotificationInfo[] {info;...... private long sequencenumber = 1;
14 MXBeans MXBean to nowy rodzaj MBean'a, umożliwiający łatwe kodowanie MBean'a odwołującego się jedynie do określonego zbioru typów. Dzięki temu MBean może być wykorzystany przez klientów, którzy nie mają dostępu do specyficznych klas określających typy występujące w MBean'ie. MXBean jest określony przez interfejs Javy JakisMXBean lub poprzez adnotację (annotation) @MXBean, oraz klasę implementującą go (nie musi się ona nazywać Jakis).
15 MXBeans Przykład: MXBean sterujący zasobem typu Queue<String>. Umożliwia on podgląd aktualnego stanu kolejki (QueueSample) zawierającego: czas, rozmiar kolejki, głowę kolejki. package com.example.mxbeans; public interface QueueSamplerMXBean { public QueueSample getqueuesample(); public void clearqueue();
MXBeans package com.example.mxbeans; import java.util.date; import java.util.queue; public class QueueSampler implements QueueSamplerMXBean { private Queue<String> queue; public QueueSampler(Queue<String> queue) { this.queue = queue; public QueueSample getqueuesample() { synchronized (queue) { return new QueueSample(new Date(), queue.size(), queue.peek()); public void clearqueue() { synchronized (queue) { queue.clear(); 16
Klasa QueueSample package com.example.mxbeans; import java.beans.constructorproperties; import java.util.date; public class QueueSample { private final Date date; private final int size; private final String head; @ConstructorProperties({"date", "size", "head") public QueueSample(Date date, int size, String head) { this.date = date; this.size = size; this.head = head; public Date getdate() { return this.date; public int getsize() { return this.size; public String gethead() { return this.head; 17
Rejestracja package com.example.mxbeans; import... public class Main { public static void main(string[] args) throws Exception { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); ObjectName name = new ObjectName( "com.example.mxbeans:type=queuesampler"); // Utworzenie QueueSampler'a Queue<String> queue = new ArrayBlockingQueue<String>(10); queue.add("request-1"); queue.add("request-2"); queue.add("request-3"); QueueSampler mxbean = new QueueSampler(queue); mbs.registermbean(mxbean, name); System.out.println("Waiting..."); Thread.sleep(Long.MAX_VALUE); 18
19 Dostęp do MXBean Do MXBean można dostać się za pomocą jconsole lub programowo: dostęp bezpośrerdni: MBeanServer mbs =... ObjectName name =... CompositeData queuesample = (CompositeData) mbs.getattribute(name, "QueueSample"); int size = (Integer) queuesample.get("size"); poprzez proxy: MBeanServer mbs =... ObjectName name =... QueueSamplerMXBean proxy = JMX.newMXBeanProxy(mbs, name, QueueSamplerMXBean.class); QueueSample queuesample = proxy.getqueuesample(); int size = queuesample.getsize();
Deskryptory Deskryptory umożliwiają przekazanie klientowi dodatkowych informacji o MBean'ie. Począwszy od Java SE 6 deskryptory są częścią JMX API. package com.example.mxbeans; import java.lang.annotation.documented; import java.lang.annotation.elementtype; import java.lang.annotation.retention; import java.lang.annotation.retentionpolicy; import java.lang.annotation.target; import javax.management.descriptorkey; @Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Author { @DescriptorKey("author") String value(); 20
21 Deskryptory Skorzystanie ze zdefinowanego deskryptora w interfejsie: package com.example.mxbeans; @Author("Mr Bean") public interface QueueSamplerMXBean { @DisplayName("GETTER: QueueSample") public QueueSample getqueuesample(); @DisplayName("OPERATION: clearqueue") public void clearqueue();
22 JMX Connectors Technologia JMX określa złącza (connectors) oparte o RMI. Służą one do połączenia i korzystania z MBean'ów znajdujących się na serwerze. Przykład: Program serwera: tworzy serwer MBean'ów, rejestruje MBean na lokalnym serwerze MBean'ów, wykonuje lokalnie operacje na MBean'ach, tworzy serwer RMI. Program kliencki: tworzy złącze RMI, rejestruje MBean na zdalnym serwerze MBean'ów, wykonuje zdalne operacje na MBean'ach.
SimpleStandard MBean public interface SimpleStandardMBean { public String getstate(); public void setstate(string s); public int getnbchanges(); public void reset(); public class SimpleStandard extends NotificationBroadcasterSupport implements SimpleStandardMBean { public String getstate() { return state; public void setstate(string s) { state = s; nbchanges++; public int getnbchanges() { return nbchanges; public int getnbresets() { return nbresets; public void reset() { state = "initial state"; nbchanges = 0; nbresets++; private String state = "initial state"; private int nbchanges = 0; private int nbresets = 0; 23
24 Program serwera public class Server { public static void main(string[] args) { try { // Inicjacja serwera MBean'ów MBeanServer mbs = MBeanServerFactory.createMBeanServer(); // Tworzenie i rejestracja SimpleStandard MBean String domain = mbs.getdefaultdomain(); String mbeanclassname = "SimpleStandard"; String mbeanobjectnamestr = domain + ":type=" + mbeanclassname + ",name=1"; ObjectName mbeanobjectname = createsimplembean(mbs, mbeanclassname, mbeanobjectnamestr);
25 Program serwera // Tworzenie serwera RMI JMXServiceURL url = new JMXServiceURL(" service:jmx:rmi:///jndi/rmi://localhost:9999/server"); JMXConnectorServer cs = JMXConnectorServerFactory. newjmxconnectorserver(url, null, mbs); // Uruchomienie serwera RMI cs.start(); System.in.read(); // Zatrzymanie serwera RMI cs.stop(); catch (Exception e) { e.printstacktrace();
Program kliencki public class Client { public static void main(string[] args) { try { // Utworzenie złącza i nawiązanie połączenia JMXServiceURL url = new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://localhost:9999/server"); JMXConnector jmxc = JMXConnectorFactory.connect(url, null); // Utworzenie listenera dla powiadomień ClientListener listener = new ClientListener(); // Pobranie połączenia MBeanServerConnection mbsc = jmxc.getmbeanserverconnection(); // Pobranie domen String domain = mbsc.getdefaultdomain(); // Utworzenie SimpleStandard MBean ObjectName stdmbeanname = new ObjectName(domain +":type=simplestandard,name=2"); mbsc.creatembean("simplestandard", stdmbeanname, null, null); // Odczytanie atrybutu mbsc.getattribute(stdmbeanname, "State"); // Ustawienie atrybutu mbsc.setattribute(stdmbeanname, new Attribute("State", "changed state")); 26
Program kliencki // Inny sposób - poprzez Proxy SimpleStandardMBean proxy = JMX.newMBeanProxy( mbsc, stdmbeanname, SimpleStandardMBean.class, true); proxy.getstate(); // Powiadomienia mbsc.addnotificationlistener(stdmbeanname, listener, null, null); // Wywołanie reset(); mbsc.invoke(stdmbeanname, "reset", null, null); // Czekanie na powiadomienie Thread.sleep(2000); // Usunięcie listener'a mbsc.removenotificationlistener(stdmbeanname, listener); // odinstalowanie MBean'a mbsc.unregistermbean(stdmbeanname); // Zakończenie połączenia jmxc.close(); catch (Exception e) { e.printstacktrace(); 27
28 Program kliencki import javax.management.notification; import javax.management.notificationlistener; public class ClientListener implements NotificationListener { public void handlenotification(notification notification, Object handback) { System.out.println("\nReceived notification: " + notification);
Dynamiczny MBean import java.lang.reflect.constructor; import java.util.iterator; import javax.management.*; public class SimpleDynamic extends NotificationBroadcasterSupport implements DynamicMBean { public SimpleDynamic() { dattributes[0] = new MBeanAttributeInfo( "State", // Nazwa "java.lang.string", // Typ "State string.", // Opis true, // Do odczytu true, // Do zapisu false); // getter is... Constructor[] constructors = this.getclass().getconstructors(); dconstructors[0] = new MBeanConstructorInfo( "Constructs a SimpleDynamic object", constructors[0]); 29
Dynamiczny MBean MBeanParameterInfo[] params = null; doperations[0] = new MBeanOperationInfo( "reset", // Nazwa "reset State and NbChanges", // Opis params, // Sygnatura (argumenty) "void", // typ wyniku MBeanOperationInfo.ACTION); // oddziaływanie INFO odczyt, ACTION zapis, ANCTION_INFO, UNKNOWN dnotifications[0] = new MBeanNotificationInfo(new String[] { AttributeChangeNotification.ATTRIBUTE_CHANGE, AttributeChangeNotification.class.getName(), "Notification when reset() method is called."); dmbeaninfo = new MBeanInfo(dClassName, ddescription, dattributes, dconstructors, doperations, dnotifications); 30
Dynamiczny MBean Interfejs DynamicBean zawiera następujące metody, które musimy zaimplementować: public Object getattribute(string attribute) throws AttributeNotFoundException, MBeanException, ReflectionException; public void setattribute(attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException; public AttributeList getattributes(string[] attributes); public AttributeList setattributes(attributelist attributes); // wywołanie operacji (metody) public Object invoke(string actionname, Object params[], String signature[]) throws MBeanException, ReflectionException; public MBeanInfo getmbeaninfo(); 31
32 Podsumowanie Technologia JMX służy do zarządzania zasobami. Sterowanie odbywa się za pośrednictwem obiektów MBean, które są udostępniane przez serwer MBean'ów. Dostęp do serwera jest możliwy za pomocą aplikacji jconsole, bezpośrednio z programu Javy oraz poprzez RMI.