Bonjour,

Je débute avec Java et d'une façon plus générale avec la programmation objet.

J'ai créé un petit utilitaire JMX destiné à récupérer les patches déployés sur un serveur weblogic 10. Mes questions n'ont rien à voir avec l'aspect fonctionnel du programme, j'aimerais que vous me donniez votre point de vue sur l'organisation du code.

J'utilise une première classe OptionsHandler pour parser les options de la ligne de commande :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 
package domain.application.util;
 
import com.martiansoftware.jsap.JSAP;
import com.martiansoftware.jsap.FlaggedOption;
import com.martiansoftware.jsap.JSAPResult;
import com.martiansoftware.jsap.JSAPException;
 
public class OptionsHandler {
 
	private static String username = null;
	private static String credential = null;
	private static String hostname = null;
	private static Integer port = null;
 
	public OptionsHandler (String[] arguments) {
		JSAP jsap = new JSAP();
 
		FlaggedOption opt1 = new FlaggedOption("username")
		.setStringParser(JSAP.STRING_PARSER)
		.setRequired(true)
		.setShortFlag('u')
		.setLongFlag("username");
		FlaggedOption opt2 = new FlaggedOption("credential")
		.setStringParser(JSAP.STRING_PARSER)
		.setRequired(true)
		.setShortFlag('c')
		.setLongFlag("credential");
		FlaggedOption opt3 = new FlaggedOption("hostname")
		.setStringParser(JSAP.STRING_PARSER)
		.setRequired(true)
		.setShortFlag('h')
		.setLongFlag("hostname");
		FlaggedOption opt4 = new FlaggedOption("port")
		.setStringParser(JSAP.INTEGER_PARSER)
		.setRequired(true)
		.setShortFlag('p')
		.setLongFlag("port");
 
		try {
			jsap.registerParameter(opt1);
			jsap.registerParameter(opt2);
			jsap.registerParameter(opt3);
			jsap.registerParameter(opt4);
		} catch (JSAPException e) {
			System.out.println("An error occured while registering parameters: "
					+ e.getMessage());
		}
 
		JSAPResult options = jsap.parse(arguments);
		username = options.getString("username");
		credential = options.getString("credential");
		hostname = options.getString("hostname");
		port = options.getInt("port");
	}
 
	public String getUsername() {
		return username;
	}
 
	public String getCredential() {
		return credential;
	}
 
	public String getHostname() {
		return hostname;
	}
 
	public Integer getPort() {
		return port;
	}
 
}
Une classe ConnectionHandler pour obtenir une connection au serveur d'application :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 
package domain.application.jmx;
 
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashMap;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;
import domain.application.util.OptionsHandler;
 
public class ConnectionHandler {
 
	private static final String PROTOCOL = "t3";
	private static final String JNDI_ROOT = "/jndi/";
	private static final String JNDI_NAME = "weblogic.management.mbeanservers.domainruntime";
	private static String username = null;
	private static String credential = null;
	private static String hostname = null;
	private static Integer port = null;
	private static MBeanServerConnection connection = null;
 
	public ConnectionHandler(OptionsHandler handler) {
		username = handler.getUsername();
		credential = handler.getCredential();
		hostname = handler.getHostname();
		port = handler.getPort();
		try {
			createConnection();
		} catch (Throwable t) {
			System.out.println(t.getMessage());
		} 
	}
 
	@SuppressWarnings("unchecked")
	public void createConnection() throws IOException,
	MalformedURLException {
		JMXServiceURL url = null;
		JMXConnector connector = null;
		url = new JMXServiceURL(PROTOCOL, hostname, port, JNDI_ROOT + JNDI_NAME);
		HashMap map = new HashMap();
		map.put(Context.SECURITY_PRINCIPAL, username);
		map.put(Context.SECURITY_CREDENTIALS, credential);
		map.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, "weblogic.management.remote");
		connector = JMXConnectorFactory.connect(url, map);
		connection = connector.getMBeanServerConnection();
	}
 
	public MBeanServerConnection getConnection() {
		return connection;
	}
 
}
Une classe (je vous le donne en mille) DataHandler pour récupérer les données (une String en l'occurence) :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 
package domain.application.jmx;
 
import javax.management.MalformedObjectNameException;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
 
import domain.application.jmx.ConnectionHandler;;
 
public class DataHandler {
 
	private static final ObjectName SERVICE;
	private static MBeanServerConnection connection;
 
	static {
		try {
			SERVICE = new ObjectName("com.bea:Name=DomainRuntimeService," +
			"Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean");
		}catch (MalformedObjectNameException e) {
			throw new AssertionError(e.getMessage());
		}
	}
 
	public DataHandler(ConnectionHandler connectionHandler) {
		connection = connectionHandler.getConnection();
	}
 
	public String getData() {
		ObjectName domainMBean = null;
		ObjectName serverRuntimeMBean[] = null;
		ObjectName adminServerRuntime = null;
		String adminServerName = null;
		String weblogicVersion = null;
		try {
			domainMBean = (ObjectName) connection.getAttribute(SERVICE,
			"DomainConfiguration");
			adminServerName = connection.getAttribute(domainMBean,
			"AdminServerName").toString();
			serverRuntimeMBean = (ObjectName[]) connection.getAttribute(SERVICE,
			"ServerRuntimes");
			for (ObjectName serverRuntime:serverRuntimeMBean) {
				if (connection.getAttribute(serverRuntime,
				"Name").equals(adminServerName)) {
					adminServerRuntime = serverRuntime;
				}
			}
			weblogicVersion = connection.getAttribute(adminServerRuntime,
			"WeblogicVersion").toString();
		} catch (Throwable t) {
			t.getMessage();
		}
		return weblogicVersion;
	}
 
}
Et pour finir une classe Main :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
package domain.application;
 
import domain.application.util.OptionsHandler;
import domain.application.jmx.ConnectionHandler;
import domain.application.jmx.DataHandler;
 
public class Main {
 
	public static void main(String[] args) {
		try {
			OptionsHandler optionsHandler = new OptionsHandler(args);
			ConnectionHandler connectionHandler = new ConnectionHandler(optionsHandler);
			DataHandler dataHandler = new DataHandler(connectionHandler);
			System.out.println(dataHandler.getData());
		}catch (Throwable t) {
			t.getMessage();
		}
	}
 
}
Toutes les remarques sont les bienvenues, mais j'aimerais savoir en particulier ce que vous pensez de l'approche retenue pour "passer" les différentes informations d'un objet à l'autre via la classe Main. En gros, je ne sais pas si c'est une bonne chose d'utiliser des getters comme je l'ai fait, s'il est bienvenu de passer des références d'objets au constructeurs des méthodes, s'il vaut mieux embarque plus de code dans le constructeur, moins dans les getters... Et je n'aime pas trop le code de la classe Main, je me dis qu'il doit y avoir moyen de faire plus élégant.

Alors les esthètes du java, je suis tout ouïe