Mostrando entradas con la etiqueta Java. Mostrar todas las entradas
Mostrando entradas con la etiqueta Java. Mostrar todas las entradas

jueves, julio 21, 2011

Acceso JMX remoto con JConsole a Tomcat

JConsole permite monitorizar en tiempo real el estado de la JVM que necesitemos y ejecutar operaciones JMX remotamente, incluso forzar GCs (Garbage Collections). Podemos acceder a nuestros procesos locales que estén ejecutando la JDK o procesos remotos que tengan habilitado el acceso remoto por JMX.

En mi caso he necesitado monitorizar un applet local y un Tomcat 6 situado en otra máquina.

JConsole es un programa que está situado en el bin de la JDK, basta con ejecutarlo para que aparezca un menú donde se elige el proceso local que está corriendo o el remoto.

Para conectarnos por JMX remotamente habrá que habilitar el servicio en la máquina virtual remota. Esto se hace incluyendo los siguientes atributos en el inicio de la JVM:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=%my.jmx.port%
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

Esta es la forma fácil e insegura, ya que estoy deshabilitando la autenticación, pero para habilitarla a partir de ficheros de configuración sería algo así:
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.password.file=jmxremote.password
-Dcom.sun.management.jmxremote.access.file=jmxremote.access

Fichero de acceso:
# The "monitorRole" role has password "QED".
# The "controlRole" role has password "R&D".
monitorRole QED
controlRole R&D

Fichero de passwords:
monitorRole tomcat
controlRole tomcat

Donde lo he probado ha sido en Windows XP, con la versión de Tomcat 6.0.20, instalada como servicio, por lo que he tenido que ejecutar tomcat6w.exe para editar, desde la pestaña Java las propiedades Java y añadir las que he comentado al principio.

Si queremos habilitar una conexión segura por SSL habría que configurar el keystore y el password, pero como no lo he probado dejo únicamente una referéncia:
http://download.oracle.com/javase/1.5.0/docs/guide/management/agent.html#remote

Aquí está la documentación para hacerlo en Tomcat 6
http://tomcat.apache.org/tomcat-6.0-doc/monitoring.html#Enabling_JMX_Remote

Saludos!

domingo, octubre 24, 2010

Creando un archetype en Maven 2 / 3

Para empezar, un archetype de maven es una plantilla que sirve para generar proyectos muy fácilmente y empezar a trabajar rápidamente. En estas plantillas se debe generar todo lo necesario para que el proyecto funcione, por lo que incluirá tanto el pom.xml, las clases main y de test y todos los resources que hagan falta según el tipo de proyecto (persistence.xml, logback.xml, etc.).

Si bien hay muchos archetypes por internet yo soy de usar la configuración que más me gusta y siempre acabo personalizando mucho mis proyectos por lo que me he acabado haciendo uno propio con las dependencias que suelo usar en un proyecto sencillo. Esto incluye lo siguiente:

- SLF4J
- Logback
- HSQLDB como in-memory database
- Hibernate como implementación de JPA
- Spring como inyector de dependencias
- Junit 4

Para generar el tutorial he utilizado lo siguiente:
- Apache Maven: 3.0
- Java version: 1.6.0_22
- Git version: 1.7.1

Como he dicho antes hay muchos archetypes, incluso hay uno para generar archetypes (maven-archetype-archetype). El caso es que si tenemos muy claro lo que vamos a hacer e incluso ya tenemos nuestro proyecto base creado lo más sencillo es crearse un archetype a partir de este proyecto. Primero vamos a hacerlo y luego explicamos la diferencia principal con crearlo desde cero.

El proyecto base

La estructura del proyecto es la siguiente.
.
├── pom.xml
└── src
├── main
│   ├── java
│   │   └── es
│   │   └── discolo
│   │   ├── app
│   │   │   └── App.java //Símplemente hace un log Hello World
│   │   ├── dao
│   │   │   ├── FooEntityDao.java //Interfaz Dao
│   │   │   └── impl
│   │   │   └── FooEntityDaoImpl.java //Implementación de JPA para ese interfaz
│   │   └── model
│   │   └── FooEntity.java //Entity para probar la integración con JPA
│   └── resources
│   ├── applicationContext.xml //Configuración de Spring
│   ├── logback.xml //Configuración de Logback
│   └── META-INF
│   └── persistence.xml //Configuración del persistence unit asociado a HSQLDB
└── test
├── java
│   └── es
│   └── discolo
│   └── test
│   ├── AbstractTest.java //Clase abstracta que configura el contexto de tests de Spring
│   └── PersistenceTest.java //Prueba la persistencia y las inyecciones de dependencias
└── resources
├── logback-test.xml //Configuración de test de Logback
└── testContext.xml //Configuración de Spring utilizada por AbstractTest

Generando el archetype a partir del proyecto

Es tan sencillo como escribir:

discolo@granada:~/workspace/jpa-spring-archetype$ mvn archetype:create-from-project
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building jpa-spring 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.0-alpha-5:create-from-project (default-cli) @ jpa-spring >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.0-alpha-5:create-from-project (default-cli) @ jpa-spring <<< [INFO] [INFO] --- maven-archetype-plugin:2.0-alpha-5:create-from-project (default-cli) @ jpa-spring --- [INFO] Setting default groupId: es.discolo [INFO] Setting default artifactId: jpa-spring [INFO] Setting default version: 1.0-SNAPSHOT [INFO] Setting default package: es.discolo [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building jpa-spring-archetype 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ jpa-spring-archetype --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 13 resources [INFO] [INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ jpa-spring-archetype --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 2 resources [INFO] [INFO] --- maven-archetype-plugin:2.0-alpha-5:jar (default-jar) @ jpa-spring-archetype --- [INFO] [INFO] --- maven-archetype-plugin:2.0-alpha-5:add-archetype-metadata (default-add-archetype-metadata) @ jpa-spring-archetype --- [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 2.360s [INFO] Finished at: Sun Oct 24 12:35:00 CEST 2010 [INFO] Final Memory: 6M/66M [INFO] ------------------------------------------------------------------------ [INFO] Archetype created in target/generated-sources/archetype [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 6.555s [INFO] Finished at: Sun Oct 24 12:35:00 CEST 2010 [INFO] Final Memory: 7M/65M [INFO] ------------------------------------------------------------------------



Bien, con esto ya tenemos en target nuestro archetype generado. Vamos a ver lo que ha hecho maven dentro de target/generated-sources/archetype. Tenemos un pom.xml que corresponde al archetype, un src y un target. En el source está la configuración del archetype que incluye el proyecto modificado para adaptarse a la configuración y la estructura de la que partió al generarse. En el target tenemos el archetype listo para instalar.

Echamos un vistazo rápido al src:

src/
├── main
│   └── resources
│   ├── archetype-resources
│   │   ├── pom.xml
│   │   └── src
│   │   ├── main
│   │   │   ├── java
│   │   │   │   ├── app
│   │   │   │   │   └── App.java
│   │   │   │   ├── dao
│   │   │   │   │   ├── FooEntityDao.java
│   │   │   │   │   └── impl
│   │   │   │   │   └── FooEntityDaoImpl.java
│   │   │   │   └── model
│   │   │   │   └── FooEntity.java
│   │   │   └── resources
│   │   │   ├── applicationContext.xml
│   │   │   ├── logback.xml
│   │   │   └── META-INF
│   │   │   └── persistence.xml
│   │   └── test
│   │   ├── java
│   │   │   └── test
│   │   │   ├── AbstractTest.java
│   │   │   └── PersistenceTest.java
│   │   └── resources
│   │   ├── logback-test.xml
│   │   └── testContext.xml
│   └── META-INF
│   └── maven
│   └── archetype-metadata.xml
└── test
└── resources
└── projects
└── basic
├── archetype.properties
└── goal.txt

Vemos que ha incluido nuestro proyecto dentro de src/main/resources/archetype-resources y que en src/main/resources/META-INF/maven existe un fichero archetype-metadata.xml, este es el que dice qué ficheros incluir y cuales no. Aunque parezca que ha respetado nuestro proyecto tal cual, no es así puesto que hace falta personalizarlo para que realmente sea una plantilla. Esto se puede ver por ejemplo en el fichero pom.xml

...
${groupId}

${artifactId}

${version}
...

Se ve como se han parametrizado los atributos que dependerán de quien genere un proyecto a partir de este archetype. Otro ejemplo en la clase de AbstractTest que empieza así:
#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package}.test;

Estas cosas son las que hacen más sencillo generar el archetype a partir de un proyecto.

Instalando el archetype

Para poder usar el archetype deberá estar instalado en nuestro repositorio con lo que ejecutamos un mvn install desde target/generated-sources/archetype:
discolo@granada:~/workspace/jpa-spring-archetype/target/generated-sources/archetype$ mvn install
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building jpa-spring-archetype 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ jpa-spring-archetype ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 13 resources
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ jpa-spring-archetype ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 2 resources
[INFO]
[INFO] --- maven-archetype-plugin:2.0-alpha-5:jar (default-jar) @ jpa-spring-archetype ---
[INFO]
[INFO] --- maven-archetype-plugin:2.0-alpha-5:add-archetype-metadata (default-add-archetype-metadata) @ jpa-spring-archetype ---
[INFO]
[INFO] --- maven-archetype-plugin:2.0-alpha-5:integration-test (default-integration-test) @ jpa-spring-archetype ---
/home/discolo/workspace/defaultJPA_bkp/target/generated-sources/archetype/target/test-classes/projects/basic/archetype.properties
[INFO]
[INFO] --- maven-install-plugin:2.3.1:install (default-install) @ jpa-spring-archetype ---
[INFO] Installing /home/discolo/workspace/defaultJPA_bkp/target/generated-sources/archetype/target/jpa-spring-archetype-1.0-SNAPSHOT.jar to /home/discolo/.m2/repository/es/discolo/jpa-spring-archetype/1.0-SNAPSHOT/jpa-spring-archetype-1.0-SNAPSHOT.jar
[INFO] Installing /home/discolo/workspace/defaultJPA_bkp/target/generated-sources/archetype/pom.xml to /home/rromero/.m2/repository/es/discolo/jpa-spring-archetype/1.0-SNAPSHOT/jpa-spring-archetype-1.0-SNAPSHOT.pom
[INFO]
[INFO] --- maven-archetype-plugin:2.0-alpha-5:update-local-catalog (default-update-local-catalog) @ jpa-spring-archetype ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.429s
[INFO] Finished at: Sun Oct 24 12:47:36 CEST 2010
[INFO] Final Memory: 6M/66M
[INFO] ------------------------------------------------------------------------

Usando el archetype

Finalmente vamos a generar un proyecto a partir del archetype. Si escribimos mvn archetype:generate nos aparecerán tanto los locales como los remotos, aunque podemos filtrar y mostrar únicamente los locales incluyendo el parámetro -DarchetypeCatalog=local

Nos vamos a una carpeta nueva:
mkdir /tmp/workspace
cd /tmp/workspace
mvn archetype:generate -DarchetypeCatalog=local
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.0-alpha-5:generate (default-cli) @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.0-alpha-5:generate (default-cli) @ standalone-pom <<< [INFO] [INFO] --- maven-archetype-plugin:2.0-alpha-5:generate (default-cli) @ standalone-pom --- [INFO] Generating project in Interactive mode [INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0) Choose archetype: 1: local -> jpa-spring-archetype (Archetype - jpa-spring-archetype)
Choose a number: : 1
Downloading: http://repository.jboss.com/maven2/es/discolo/archetype/jpa-spring-archetype/1.1-SNAPSHOT/maven-metadata.xml
Downloading: http://snapshots.jboss.org/maven2/es/discolo/archetype/jpa-spring-archetype/1.1-SNAPSHOT/maven-metadata.xml
Define value for property 'groupId': : com.mycorp
Define value for property 'artifactId': : prueba-archetype
Define value for property 'version': 1.0-SNAPSHOT: :
Define value for property 'package': com.mycorp: :
Confirm properties configuration:
groupId: com.mycorp
artifactId: prueba-archetype
version: 1.0-SNAPSHOT
package: com.mycorp
Y: : y
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 46.169s
[INFO] Finished at: Sun Oct 24 12:54:19 CEST 2010
[INFO] Final Memory: 7M/66M
[INFO] ------------------------------------------------------------------------

Perfecto! Con esto ya tenemos nuestro proyecto listo para echar a andar. Vamos a pasar los tests por si algo no ha ido bien.
...
Results :

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0

12:57:13.824 [Thread-1] INFO o.hibernate.impl.SessionFactoryImpl - closing
12:57:13.824 [Thread-1] INFO o.h.c.DriverManagerConnectionProvider - cleaning up connection pool: jdbc:hsqldb:mem:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...

Pues esto es todo, espero que os ahorre algo de tiempo a la hora de empezar vuestros proyectos. El código fuente en un repositorio de git, en codaset, por si queréis consultarlo o mejorarlo.

http://codaset.com/discolo/jpa-hibernate-archetype

Saludos,
Discolo.

martes, abril 13, 2010

Alojando múltiples dominios en JBoss (Hosting multiple domains in JBoss)

 Esto es una situación que creo que es común, sobretodo en entornos corporativos. Voy a explicar los pasos necesarios y las fuentes utilizadas para conseguirlo (espero que se entienda xD)

Tenemos 2 instancias de Jboss y en cada máquina hay 2 interfaces: Servicio y Operación y Mantenimiento (O&M) por lo tanto, necesitábamos tener expuestos por la interfaz de servicio los WebServices que se usarán por los clientes y el resto (portal de administración, jmx-console, etc.) por el de O&M. A parte es interesante evitar modificar el máximo número de ficheros de configuración, sobretodo de las aplicaciones de Jboss.


En el enlace siguiente he visto toda la información que hace falta:

http://www.fusioncube.net/index.php/hosting-multiple-domains-with-jboss


Aquí se puede entrar en más detalle:

http://tomcat.apache.org/tomcat-5.5-doc/config/


Partimos de que JBoss AS se a arrancado en el puerto 0.0.0.0 para que escuche por todos los interfaces.


Ya que las aplicaciones Web se despliegan en la instancia de tomcat que incluye jboss (jboss-web.deployer) es ahí donde configuraremos el fichero server.xml.


Existen 3 partes importantes en este fichero:


1º Definición del Engine y del default host. El defaultHost debe ser un vhost válido definido dentro del Engine y será donde se desplegarán todas las aplicaciones que no tengan un virtual-host definido.
<Engine name="jboss.web" defaultHost="localhost">
2º Localhost. Ya existe en la configuración por defecto y le añadimos los alias para que todo lo que entre por localhost o por uno de sus alias irá a las aplicaciones que no tengan configurado un virtual-host en su jboss-web.xml (puesto que es el defaultHost).
<Host name="localhost" autoDeploy="false" deployOnStartup="false" deployXML="false"
           configClass="org.jboss.web.tomcat.security.config.JBossContextConfig" >
    <Alias>myHostname_om</Alias>
    <Alias>172.1.3.137</Alias>
    <Valve className="org.jboss.web.tomcat.service.jca.CachedConnectionValve"
        cachedConnectionManagerObjectName="jboss.jca:service=CachedConnectionManager"
        transactionManagerObjectName="jboss:service=TransactionManager" ></Valve> </Host>
3º Definición de cada virtual host extra. Un virtual host permite separar las aplicaciones web y aplicar distintas configuraciones. En este caso definimos uno para la lógica de servicio con 2 alias, uno para resolver por hostname y otro para resolver por IP. El name del host puede ser tanto una ip como un hostname, pero en este caso para llamar al host de una forma genérica se le ha llamado vhost_ls.
<Host name="vhost_ls" autoDeploy="false" deployOnStartup="false" deployXML="false"
           configClass="org.jboss.web.tomcat.security.config.JBossContextConfig">
    <Alias>myHostname_ls</Alias>
    <Alias>192.168.2.137</Alias>
    <Valve className="org.jboss.web.tomcat.service.jca.CachedConnectionValve"
        cachedConnectionManagerObjectName="jboss.jca:service=CachedConnectionManager"
        transactionManagerObjectName="jboss:service=TransactionManager" ></Valve> </Host>
Una vez configurado el vhost se modificará la configuración de cada aplicación web que queremos que vaya al vhost_ls. Editando su fichero ./WEB-INF/jboss-web.xml, añadiremos lo siguiente (funciona tanto para el hostname como la ip):

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>       
    <virtual-host>myHostname_ls</virtual-host>
    <context-root>/</context-root>
</jboss-web>


Esto es lo que yo he configurado en nuestro entorno. En teoría, quedaría mejor tener el vHost-localhost el vHost-lógicaServicio y el vHost-O&M cada uno con sus alias, incluso quitar localhost, así solo poder atacar por esos dos, poniendo como defaultHost el de O&M, pero en la práctica no he sido capaz de hacerlo funcionar, así que si alguien lo intenta y lo consigue que me avise.


Un saludo y espero que os sea de ayuda.

Discolo