ReadMe escrito sintetizando conteúdos presentes em:
Brian Chan: Liferat Basic Training OSGI.
Quitumba:YouTube Playlist.
É uma especificação que produzir um sistema dinâmico de componentes Java, com o objetivo de reduzir a complexidade de um software através de uma arquitetura modular orientada a serviços.
São modulos que possuem identificadores únicos (Manifesto) com cabeçalhos específicos (válidos) e devem ser armazenados em um arquivo JAR. Podemos dizer que o Bundle é a unidade básica de modularidade.
Na identificação do bundle temos dois cabeçalhos específicos no manifesto que são utilizados para identificar um Bundles, são eles:
- Bundle-SymbolicName
- Bundle-Version
Exemplo: version= [ 1.2, 2.0 )
Nesse caso estamos informando que as versões que devem ser utilizadas pelo meu Bundles está entre 1.2 e inevitavelmente antes da 2.0 (existem funcionalidades incompatíveis com as versões anteriores na versão 2.0)
Ou seja, se observarmos bem. Utilizamos o colchete para incluir versões e o parenteses para excluir versões incompatíveis
Um Bundle inevitavelmente possui 6 estados, sendo eles:
- Installed
- Resolved
- Starting
- Active
- Stopping
- Uninstalled
Podemos gerenciar o ciclo de vida de um Bundle usando linha de comando. Utilizando o Gogo Shell que é um recurso que permite acessar o container OSGI utilizando o Telnet.
Uma vez presente no Gogo Shell podemos utilizar alguns comandos para gerenciar o bundle como:
- install caminho/para/bundle/nomeBundle.jar
Após o bundle ser instalado será gerado bundle ID, esse ID pode ser utilizado na execução dos outros comandos que gerenciam o estado de um bundle.
- uninstall bundleId
- resolve bundleId
- update bundleId
- refresh bundleId
- start bundleId
- stop bundleId
Componente é um objeto que possui uma funcionalidade específica. Exemplo: Serviço, Servelet, Portlet e Comandos.
Qualquer classe dentro de um Bundle pode ser declarada como um componente.
Component é um objeto gerenciado pelo OSGI e possui um ciclo de vida, assim como o bundle.
O componente ficará dentro do Bundle e o Container OSGI cuidará dos dois.
A vantagem de utilizar uma classe como um componente é que elas podem ser publicadas como serviços e estar disponíveis para outros componentes. Além disso, possui um ciclo de vida independente e reutilizado, podendo possuir propriedades e ativação.
O @component é usado para registrar um componente dentro do registro de serviços.
O serviço é um componente registrado pelo Service Registry no container do OSGI.
O bundle pode declarar as funcionalidades que ele fornece como serviço OSGI.
Além disso, o bundle pode pedir por funcionalidades específicas nos serviços OSGI.
O Service Registry funciona como uma distribuidora que recebe serviços exportados pelos Bundles e envia serviços para os Bundles que estão solicitando.
É um Framework de ingestão de dependência OSGI, permite declarar e consumir serviços via XML e anotações. Inicializa a classe, injeta as dependências, ativa os componentes e registra os serviços.
O @reference é utilizado para solicitar ao registro de serviço uma referência de um componente específico.
Inicialmente criamos um diretório que irá conter nosso projeto.
Em seguida, criamos o arquivo settings.gradle
buildscript {
dependencies {
classpath group: "com.liferay", name: "com.liferay.gradle.plugins.workspace", version: "latest.release"
}
repositories {
mavenLocal()
maven {
url "https://repository-cdn.liferay.com/nexus/content/groups/public"
}
}
}
apply plugin: "com.liferay.workspace"
As informações presentes em settings.gradle são responsáveis por criar o com.liferay.workspace Gradle Plugin
Em seguida é criado o arquivo gradle.properties que seleciona uma versão específica do Portal
gradle.properties
liferay.workspace.product=portal-7.3-ga7
Inicialmente criamos uma estrutura de pasta.
mkdir -p basic-training-able-impl/src/main/java/com/liferay/basic/training/able/internal/activator
Posteriormente criamos um arquivo .java, no diretório recém criado activate, nomeado de AbleBundleActivator e adicionamos as seguintes informações:
package com.liferay.basic.training.able.internal.activator;
public class AbleBundleActivator {
public AbleBundleActivator() {
System.out.println("Constructing AbleBundleActivator");
}
}
Porém ao tentarmos compilar nosso programa:
./gradlew classes
Iremos perceber que as features Gradle utilizadas nesse Build estão depreciadas, mas o comando foi executado com sucesso.
Porém o diretório de compilação build não foi criado.
Ainda em nosso diretório activator devemos criar um arquivo de configuração com os metadados básicos necessários para os módulos OSGI.
code basic-training-able-impl/bnd.bnd
Bundle-Name: Liferay Basic Training Able Implementation
Bundle-SymbolicName: com.liferay.basic.training.able.impl
Bundle-Version: 1.0.0
Em seguida, iremos criar um arquivo build.gradle
touch basic-training-able-impl/build.gradle
Um arquivo build.gradle informa ao Liferay Workspace que esse diretório é um módulo Java.
Finalmente, ao tentarmos compilar novamente nosso programa:
./gradlew classes
Iremos perceber que um novo diretório (build) se encontra em basic-training-able-impl.
Agora podemos deployar nosso modulo:
./gradlew deploy
Entretanto nosso novo módulo com.liferay.basic.training.able.impl.jar ainda não pode ser lido pela Liferay(Ainda não enviamos nosso arquivo para iamgem Docker).
Podemos levantar uma imagem Docker da Liferay para constatar:
d run --name ephesians-liferay --rm -it -p 8080:8080 liferay/portal:7.3.6-ga7
O name informa o nome do nosso container Docker e o --rm configura o container para ser removido após a finalização do mesmo, não tendo suas informações persistidas.
Se analizarmos os módulos dentro da imagem Docker em opt/liferay/osgi/modules:
d exec -it ephesians-liferay /bin/ls /opt/liferay/osgi/modules
Iremos receber como retorno uma pasta vazia.
Agora iremos enviar nosso novo módulo recém deployado para o caminho opt/liferay/osgi/modules dentro da imagem Docker:
d cp bundles/osgi/modules/com.liferay.basic.training.able.impl.jar ephesians-liferay:/opt/liferay/osgi/modules
E se executarmos outro ls dentro do Docker:
d exec -it ephesians-liferay /bin/ls /opt/liferay/osgi/modules
Iremos receber como resposta:
com.liferay.basic.training.able.impl.jar
Porém, existe uma maneira de Deployar nosso arquivo jar e já envia-lo para o nosso caminho /opt/liferay/osgi/modules substituindo o nosso ./gradlew deploy + docker cp...:
./gradlew deploy -Ddeploy.docker.container.id=ephesians-liferay
Se executarmos novamente o ls no diretório de módulos do Docker podemos perceber que iremos receber como retorno:
com.liferay.basic.training.able.impl.jar
com.liferay.basic.training.able.impl-1.0.0.jar
Em seguida finalizamos a execução do nosso container docker e inicializamos novamente. Com isso, será gerada outra imagem totalmente dissociada da imagem anterior.
Podemos repetir o processo com a nova imagem Docker:
d run --name ephesians-liferay --rm -it -p 8080:8080 liferay/portal:7.3.6-ga7
./gradlew deploy -Ddeploy.docker.container.id=ephesians-liferay
E verificarmos que o arquivo deployado já consta no nosso Docker:
d exec -it ephesians-liferay /bin/ls /opt/liferay/osgi/modules
Retorno:
com.liferay.basic.training.able.impl-1.0.0.jar
E por fim, se precisarmos atualizar o módulo deployado:
./gradlew clean deploy -Ddeploy.docker.container.id=ephesians-liferay
Esse comando irá deletar os objetos buildados antes de deployar novamente, forcando o Gradle a ser recompilado.