jueves, 21 de octubre de 2021

Desarrollo y despliegue de un servicio en Weblogic 14c

Hoy vamos a ver como crear un web service (tanto SOAP como REST), que debe desplegarse en un contenedor de aplicaciones empresariales. Concretamente en Weblogic. En apariencia es algo sencillo, pero también es verdad que al ser un servidor propiedad de Oracle y no Open Source, a veces es un poco difícil encontrar información. Así que esperamos aclarar un poco su funcionamiento básico a través de este post. 

Debemos recordar que este tipo de servidores vienen con un conjunto de librerías que implementan las especificaciones de Java y Jakarta EE. Esta es una de las razones por los que son más pesados, que un simple contenedor de servlet. Aparte de que incluyen bastante más funcionalidades asociadas a dichas especificaciones. 

Por tanto a la hora de crear una aplicación que vayamos a desplegar en Weblogic o otro tipo de contenedor de aplicaciones empresariales, debemos indicar cuales son las API que implementa. Con el beneficio de que además no es necesario añadir dichas implementaciones, puesto que ya se encuentran en el servidor. Debido a eso, simplemente deberemos indicar en el fichero pom.xml cuales son dichas interfaces y que todas tienen de ámbito provided, puesto que se encuentran en el servidor. 

<!-- weblogic dependencies -->
<dependency>    <!-- Java EE -->
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>8.0</version>
    <scope>provided</scope>
</dependency>
<dependency>    <!-- Java EE EJB -->
    <groupId>javax.ejb</groupId>
    <artifactId>javax.ejb-api</artifactId>
    <version>3.2.2</version>
    <scope>provided</scope>
</dependency>
<dependency>    <!-- Java EE Servlet -->
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.0</version>
    <scope>provided</scope>
</dependency>
<dependency>    <!-- Java EE JSP -->
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>javax.servlet.jsp-api</artifactId>
    <version>2.3.0</version>
    <scope>provided</scope>
</dependency>
<dependency>    <!-- Java EE JSF -->
    <groupId>javax.faces</groupId>
    <artifactId>javax.faces-api</artifactId>
    <version>2.3</version>
    <scope>provided</scope>
</dependency>
<dependency>    <!-- Java EE Common Annotationss -->
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
    <scope>provided</scope>
</dependency>
<dependency>    <!-- Java EE Bean Validation -->
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.0.Final</version>
    <scope>provided</scope>
</dependency>
<dependency>    <!-- Java API for JSON Processing -->
    <groupId>javax.json</groupId>
    <artifactId>javax.json-api</artifactId>
    <version>1.1</version>
    <scope>provided</scope>
</dependency>
<dependency>    <!-- Java API for JSON Binding -->
    <groupId>javax.json.bind</groupId>
    <artifactId>javax.json.bind-api</artifactId>
    <version>1.0</version>
    <scope>provided</scope>
</dependency>
<dependency>    <!-- Java API for XML-Based Web Services -->
    <groupId>javax.xml.ws</groupId>
    <artifactId>jaxws-api</artifactId>
    <version>2.3.0</version>
    <scope>provided</scope>
</dependency>
<dependency>    <!-- Java API for RESTful Web Services (JAX-RS) -->
    <groupId>javax.ws.rs</groupId>
    <artifactId>javax.ws.rs-api</artifactId>
    <version>2.1</version>
    <scope>provided</scope>
</dependency>
<dependency>    <!-- Contexts and Dependency Injection for Java EE -->
    <groupId>javax.enterprise</groupId>
    <artifactId>cdi-api</artifactId>
    <version>2.0</version>
    <scope>provided</scope>
</dependency>
<dependency>    <!-- Expression Language (EL) -->
    <groupId>javax.el</groupId>
    <artifactId>javax.el-api</artifactId>
    <version>3.0.0</version>
</dependency>

Para la creación de los web services en verdad no necesitamos tantas librerías, pero este listado nos puede servir de referencia. Para el servicio SOAP requeriremos de la librería jaxws-api y para el servicio REST de la librería javax.ws.rs-api

La idea principal es que ambos servicios sean muy básicos y funcionen prácticamente igual. Con la única diferencia de las anotaciones que permitirán que un servicio se genere como SOAP o REST. 

Empezaremos primero por el más antiguo, el servicio SOAP. La clase que implemente nuestro servicio debe tener la anotación @WebService. A la cual le podemos indicar el nombre de dicho servicio. Y cada uno de los métodos que queramos exponer deberán llevar la anotación @WebMethod, a los cuales también le podemos indicar los nombres asociados. Ejemplo:

@WebService(serviceName = "BookSoapService")
public class BookServiceImpl implements BookService {

    private static Map<Integer, Book> books = new HashMap<>();

    static {
	books.put(1, new Book(1, "Dune", "Frank Herbert"));
	books.put(2, new Book(2, "The stars my destination", "Alfred Bester"));
	books.put(3, new Book(3, "Ender's game", "Orson S. Card"));
    }

    @Override
    @WebMethod(operationName = "getById")
    public Book getById(final Integer id) {
	return books.get(id);
    }
}

Una vez desplegado el servicio, podremos acceder a su WSDL, generado automáticamente, a través de la siguiente URL: http://localhost:7001/weblogicWS/BookSoapService?wsdl.

Ahora veremos como hacer el servicio REST. Para ello deberemos añadir a nivel de clase la anotación @Path e indicar la ruta principal de acceso a dicho servicio. Este paso no es del todo necesario, puesto que podemos poner directamente dicha anotación a cada método, pero poniéndolo a nivel de clase evitamos repetir parte de dicha ruta. Luego en cada método, y en función de la operación que vaya a realizar, deberemos indicar la anotación asociada al método HTTP a utilizar. Puede ser @DELETE, @GET, etc. Hay otras anotaciones que nos pueden ayudar a obtener la información que viaja en la llamada. Como pueden ser @CookieParam, @HeaderParam, @PathParam o @QueryParam

@Path("/book")
public class BookRestServiceImpl implements BookService {

    private static Map<Integer, Book> books = new HashMap<>();

    static {
	books.put(1, new Book(1, "Dune", "Frank Herbert"));
	books.put(2, new Book(2, "The stars my destination", "Alfred Bester"));
	books.put(3, new Book(3, "Ender's game", "Orson S. Card"));
    }

    @Override
    @GET
    @Path("/{id}")
    @Produces("application/json")
    public Book getById(@PathParam("id") final Integer id) {
	return books.get(id);
    }
}

Una vez desplegado el servicio, podremos invocarlo a través de la siguiente URL: http://localhost:7001/weblogicWS/resources/book/1.

Y una vez que tenemos nuestros web services, vamos a desplegarlos. Para ello lo primero será poner en marcha el servidor. Esto podemos hacerlo descargándonoslo e instalándolo en nuestra máquina, a través de este enlace. O como es habitual hoy en día y para pruebas en desarrollo, levantarlo como una instancia de Docker. Este último será el método que veremos. 

Pero para poder utilizar una instancia de docker del servidor necesitaremos realizar los siguientes pasos:

  • Crear una cuenta en en Oracle.com Network
  • Acceder a la página de Oracle Container Registry, lógate con la cuenta creada en el paso anterior y acepta la licencia de usuario. Si no ves dicha licencia directamente, accede a una de las imágenes y aparecerá en la parte superior derecha. 
  • Logate en el Hub de Oracle a través del comando docker login container-registry.oracle.com.
  • Descarga la imagen deseada a través del comando docker pull container-registry.oracle.com/middleware/weblogic:${TAG}. Puedes ver los distintos tags aquí
Ahora que tenemos la imagen descargada necesitamos montar un volumen que nos permita indicar donde se encuentra nuestro fichero domain.properties. Este fichero de configuración nos permitirá principalmente el usuario y contraseña. A través de un comando similar a este:

docker run -p 7001:7001 -p 9002:9002 --name wl14c \
-v ${PATH_TO_DOMAIN_PROPERTIES}:/u01/oracle/properties \
container-registry.oracle.com/middleware/weblogic:14.1.1.0-dev-8

Una vez arrancado, podemos acceder a la consola de administración a través de la URL: https://localhost:9002/console/ y acceder a ella con el usuario y contraseña indicado en el fichero de configuración. 

Ya solo quedaría desplegar el servicio. Lo podemos hacer de varias formas, incluso a través de una API REST. Pero las más sencillas pasan por copiar el war o ear a una carpeta del servidor dentro de la instancia de Docker. Lo cual podemos realizar con un comando similar a este:

docker cp weblogicWS.war wl14c:/tmp/weblogicWS.war

 Como comentábamos anteriormente, lo podemos hacer de varias formas:
  1. Si el fichero lo pegamos en la carpeta /u01/oracle/user_projects/domains/base_domain/autodeploy el fichero se desplegará automáticamente. 
  2. Si lo pegamos en otra carpeta a través de la consola de Administración y la opción Despliegues tras pulsar el botón Instalar. Podremos seleccionar la ruta y fichero que hemos copiado anteriormente e instalarlo tras seleccionar unas opciones de despliegues. 
  3. También podemos desplegarlo a través de la utilidad weblogic.Deployer. Tener en cuenta que esta opción no esta disponible en la versión para desarrollo.  

docker exec -it wl14c sh
$ cd /u01/wlsdomain/base_domain/bin
$ . setDomainEnv.sh
$ java weblogic.Deployer -adminurl t3://localhost:7001 -user user1 -password welcome1 \
-name weblogicWS -targets base_domain -deploy /tmp/weblogicWS.war

Por último, vamos a indicar como debemos configurar el repositorio de Oracle si deseamos utilizarlo. Para ello primero debemos tener un usuario de acceso a Oracle.com Network, puede ser el mismo que utilizamos para descargas las imágenes del hub de Oracle. 

Ese usuario debemos configurarlo asociado al servidor en el fichero settings.xml que se encuentra en la ruta: ~/.m2/settings.xml. Tal y como mostramos a continuación:

<!-- https://docs.oracle.com/middleware/1213/core/MAVEN/config_maven_repo.htm#MAVEN9017 -->
<server>
    <id>maven.oracle.com</id>
    <username>user@mail.com</username>
    <password>{Z8Gn4wUfjN0Hsiu44T+FwfAjpRYY62ycDxKU9V7u/ps=}</password>   
        <configuration>
        <basicAuthScope>
            <host>ANY</host>
            <port>ANY</port>
            <realm>OAM 11g</realm>
        </basicAuthScope>
        <httpConfiguration>
            <all>
                <params>
                    <property>
                        <name>http.protocol.allow-circular-redirects</name>
                        <value>%b,true</value>
                    </property>
                </params>
            </all>
        </httpConfiguration>
    </configuration>
</server>

Y luego deberemos añadir los repositorios de Oracle. Estos podemos indicarlos también de forma global en el fichero settings.xml o de forma específica en cada uno de los pom.xml de los proyectos que vayan a usarlo. 

<repositories>
	<repository>
		<id>maven.oracle.com</id>
		<releases>
			<enabled>true</enabled>
		</releases>
		<snapshots>
			<enabled>false</enabled>
		</snapshots>
		<url>https://maven.oracle.com</url>
		<layout>default</layout>
	</repository>
</repositories>
<pluginRepositories>
	<pluginRepository>
		<id>maven.oracle.com</id>
		<url>https://maven.oracle.com</url>
	</pluginRepository>
</pluginRepositories>

Y esto es todo. Aunque no hemos hecho gran cosa, hemos tenido que autenticarnos en Oracle, y configurar varios aspectos para el correcto desarrollo y despliegue de nuestra aplicación, además hemos recopilado como realizar un proceso completo para hacerlo en un servidor Weblogic. Si queréis ver el código de la aplicación, lo tenéis aquí

No hay comentarios:

Publicar un comentario