Objetivo


Esse documento tem como objetivo principal mostrar como funciona o processo de empacotamento de uma versão do Storex Custom.

Para isso vamos precisar falar um pouco sobre o Application Updater, que é utilizado para distribuir e aplicar o pacote de atualização nas lojas e componentes. Vamos falar também sobre o Apache Maven, que é utilizado para fazer o empacotamento da versão a ser distribuída.


Application Updater


O Application Updater é o responsável por realizar as atualizações de versões dos componentes do Storex. Ele sempre é executado localmente no processo de inicialização dos componentes e tem como objetivos verificar se existe alguma versão a ser aplicada e, ao localizar um novo pacote, realizar a atualização da versão.O pacote é um arquivo de extensão PKG, que fica localizado dentro de p2k/bin/downloads. O Application Updater realiza o desempacotamento desse arquivo e em seguida move os arquivos, que estão dentro dele, para seus devidos lugares.


Arquivo PKG

Para que o Application Updater reconheça o arquivo PKG como válido, ele precisa conter um arquivo XML chamado update e uma pasta chamada filetypes. Conforme imagem ao lado:








Arquivo update.xml

O arquivo update.xml contem as informações a respeito do pacote de atualização. Segue um exemplo ao lado:

tag <id> identifica o tipo do componente ao qual o pacote de atualização corresponde. Esse exemplo é de um pacote de atualização para os PDVs das lojas. No caso do pacote do EP, essa mesma tag ficaria <id>LINX-STOREX-EP</id>.

tag <version> possui o número da versão que será aplicada no componente.








Pasta filetypes

Dentro de filetypes temos as pastas other e properties. A pasta other contem todos os arquivos que serão atualizados dentro de /p2k. A pasta properties contem os arquivos de extensão .properties com as property keys que serão atualizadas.








A pasta other contém todos os arquivos que serão copiados para dentro da pasta indicada na tag <rootPath> que existe no arquivo update.xml. Nesse caso, o rootPath é /p2k. Dentro de other/overwrite temos as pastas: bin, lib e temp. Todo o conteúdo da pasta bin será copiado para a pasta /p2k/bin do componente. Ou seja, o que existir será sobrescrito. A mesma coisa vai acontecer para o conteúdo das pastas lib e temp.






Na pasta properties existem as pastas delete-key e update-key. Elas armazenam os arquivos .properties que serão atualizados na aplicação. Essa atualização é feita à nível das keys, ou seja, o Application Updater não sobrescreve os arquivos. Primeiro é realizada a remoção de cada uma das property key existentes dentro dos arquivos da pasta delete-key. Em seguida ele atualiza todas as property key existentes nos arquivos que estão dentro da pasta update-key.


Atenção: Não recomendamos mais o uso de arquivos properties para manutenção de parâmetros. O caminho recomendado é a utilização do servidor de configurações.



Dentro de delete-key encontramos os arquivos que serão utilizados para fazer a exclusão das parametrizações que não serão mais utilizadas. Mais abaixo vamos citar um exemplo.







Como exemplo vamos olhar o conteúdo do arquivo motivosCancelamento.properties, que está dentro da pasta delete-key. O processo de atualização vai procurar pelo arquivo motivosCancelamento.properties que existe dentro do caminho /p2k/bin. Vai localizar cada uma das linhas que começam com as keys acima e vai removendo uma a uma do arquivo original.




Assumindo que o arquivo motivosCancelamento.properties atual, que está dentro da pasta /p2k/bin, contenha o seguinte conteúdo:










Após a execução do processo de atualização o arquivo, que está dentro da pasta /p2k/bin, motivosCancelamento.properties ficará com o seguinte conteúdo:





Conteúdo do update.xml
<application>
     <id>PDV</id>
     <vendor>LINX</vendor>
     <description>POS</description>
     <version>2.18.0.22</version>
     <rootPath>..</rootPath>
     <packageInfo>
           <allowRollback>false</allowRollback>
           <type>full</type>
     </packageInfo>
</application>










Conteúdo de motivosCancelamento.properties
ANULACAO_3
DEVOLUCAO_3
CANCELAMENTO_3
motivosCancelamento.properties antes da exclusão das keys
DEVOLUCAO_3=Troca por defeito
DEVOLUCAO_2=Troca por modelo
DEVOLUCAO_1=Troca por Tamanho

CANCELAMENTO_3=Cartão não autorizado/sem limite
CANCELAMENTO_2=Desistência da compra
CANCELAMENTO_1=Erro Operacional

ANULACAO_3=Desistência da compra
ANULACAO_2=Alteracao Forma de pagamento
ANULACAO_1=Erro Operacional
motivosCancelamento.properties após a exclusão das keys
DEVOLUCAO_2=Troca por modelo
DEVOLUCAO_1=Troca por Tamanho

CANCELAMENTO_2=Desistência da compra
CANCELAMENTO_1=Erro Operacional

ANULACAO_2=Alteracao Forma de pagamento
ANULACAO_1=Erro Operacional

Apache Maven


O Storex Custom utiliza o projeto Apache Maven para organizar e automatizar o processo de build e que é utilizado para gerar o pacote final de distribuição. O Maven utiliza o arquivo pom.xml que fica na raiz do projeto, para realizar essa execução.


Entendendo o arquivo pom.xml

O arquivo POM (Project Object Model), presente no diretório-raiz do projeto, contém todas as informações que o Maven necessita para interagir corretamente com o projeto. Ele utiliza o formato XML e relaciona todas as dependências, repositórios e faz o detalhamento da estratégia de build do projeto.
















Repositório Maven

Local central onde o Maven vai buscar todos os artefatos necessários para o build do projeto. No caso do Storex Custom, os projetos utilizam um repositório remoto. O mesmo encontra-se configurado no pom.xml dos projetos, conforme exemplo ao lado:






Adicionando dependências

No arquivo POM.xml podemos definir quais são as dependências necessárias ao projeto. Portanto, se quisermos adicionar uma nova biblioteca que será utilizada no projeto, basta irmos no nosso POM.xml e adicionar uma dependência (dependency) dentro das nossas dependecies especificando o groupId, artifactId e a version. Conforme exemplo ao lado:





Processo de Build

Após todas as dependências estarem configuradas e serem gerenciadas pelo Maven, podemos iniciar o processo de build. O processo de build segue algumas fases (indicada pela tag <phases>) desde limpar o diretório de destino do projeto (initialize), compilar (compile), executar algumas ações antes de empacotar (prepare-package), até chegar na etapa de empacotar o projeto (package). Todas as fases seguidas no processo de build, possuem seus respectivos plugins e dentro do arquivo pom.xml podemos encontrá-los dentro da tag representada ao lado.



Fase initialize

O primeiro passo da execução do Build é a limpeza do diretório de compilação, ou seja, do diretório destino para onde os arquivos serão copiados. Isso é executado pelo plugin <artifactId>maven-clean-plugin</artifactId>. Nele está configurado o diretório de destino que deve estar limpo antes de iniciar a fase prepare-package.


















Fase prepare-package

Essa fase tem o objetivo de realizar quaisquer operações necessárias para preparar um pacote antes do empacotamento propriamente dito. Nessa etapa todas as dependências que estão relacionadas na tag <dependencies> serão copiadas para a pasta lib do diretório de destino do projeto. Além disso, será escrito o conteúdo no arquivo update.xml que fará parte do pacote final.

Ao lado, podemos ver os plugins responsáveis por fazer a cópia das dependências e escrever o conteúdo do arquivo update.xml.




































Fase package

Essa é a etapa onde ocorre a geração do pacote. Nela são seguidas as seguintes etapas:

  • O merge dos arquivos XML de configuração para o componente em questão.

  • Geração do arquivo .jar do componente em questão, com a compilação do código e o conteúdo da pasta resources.

  • A criação da estrutura de pastas que será usada para formar o arquivo PKG. 

  • A captação de todos os  artefatos que foram copiados na fase prepare-package para dentro da pasta lib. Como também a cópia de todo o conteúdo da pasta filetypes.

  • A última tarefa desta etapa é a compactação da estrutura de pastas para onde foram copiados todos os artefatos, gerando ao final um arquivo com extensão .PKG, que corresponde ao pacote da versão que será disponibilizado para atualização.


Ao lado, podemos ver os plugins configurados para realizar a compilação do projeto e gerar o arquivo .jar do componente que será colocado dentro do pacote de final.




















Ao lado, podemos ver o plugin configurado para fazer a cópia do arquivo jar para dentro da pasta /lib que fica no diretório de build do projeto. Além disso, ele também extrai do .jar do projeto Standard o xml de configuração e salva na pasta.
































Ao lado, podemos ver o plugin configurado para preparar o arquivo XML com toda a parametrização do componente para ser submetida ao servidor de configurações.

Ele faz um merge entre o arquivo XML de configuração do Standard, extraído no passo anterior, com o arquivo de configuração do projeto do cliente.
















O plugin ao lado, possui a responsabilidade de gerar o arquivo final PKG. Ele é quem cria toda a estrutura de diretórios que formam o arquivo PKG.

Depois dessa criação, ele move todos os arquivos que farão parte do pacote, para dentro dos respectivos diretórios. Ao finalizar, ele faz a compactação do diretório raiz do pacote, gerando um arquivo .zip.

Em seguida ele muda a extensão do arquivo de .zip para .PKG. Finalizando assim a criação do pacote que será distribuído para as lojas e componentes.



Repositório remoto das dependências
<repositories>
     <repository>
        <id>maven-group</id>
        <url>http://a-srvrec013:8081/repository/maven-public</url>
     </repository>
</repositories> 



Tag dependency
<dependencies>
   <dependency>
	  <groupId>org.apache.pdfbox</groupId>
	  <artifactId>pdfbox</artifactId>
	  <version>2.0.7</version>
   </dependency>
</dependencies>


Tag build onde encontramos os plugins
<build>
  <plugins>
      <!-- local do POM.xml onde são configurados os plugins que serão executados no processo de build -->
  </plugins>
</build>


Plugins executados na fase initialize
<plugin>
	<artifactId>maven-clean-plugin</artifactId>
	<version>3.0.0</version>
	<executions>
		<execution>
			<id>auto-clean</id>
			<phase>initialize</phase>
			<goals>
				<goal>clean</goal>
			</goals>
		</execution>
		<execution>
			<id>limpa-diretorio-compilacao</id>
			<phase>initialize</phase>
			<goals>
				<goal>clean</goal>
			</goals>
			<configuration>
				<filesets>
					<fileset>
						<directory>${project.dist.dir}/</directory>
					</fileset>
				</filesets>
			</configuration>
		</execution>
	</executions>
</plugin>



Plugins executados na fase prepare-package
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-dependency-plugin</artifactId>
	<version>3.1.1</version>
	<executions>
		<execution>
			<id>copy-dependencies</id>
			<phase>prepare-package</phase>
			<goals>
				<goal>copy-dependencies</goal>
			</goals>
			<configuration>
				<outputDirectory>${project.build.directory}/lib</outputDirectory>
				<overWriteReleases>false</overWriteReleases>
				<overWriteSnapshots>false</overWriteSnapshots>
				<overWriteIfNewer>true</overWriteIfNewer>
			</configuration>
		</execution>
	</executions>
</plugin>

<plugin>
	<groupId>ru.yaal.maven</groupId>
	<artifactId>write-text-files-maven-plugin</artifactId>
	<version>1.1</version>
	<configuration>
		<charset>${project.build.sourceEncoding}</charset>
		<files>
			<file>
				<path>${project.build.directory}/${pkg.dir.name}/update.xml</path>
				<lines>
					<line>&lt;application&gt;</line>
					<line>&lt;id&gt;PDV&lt;/id&gt;</line>
					<line>&lt;vendor&gt;LINX&lt;/vendor&gt;</line>
					<line>&lt;description&gt;POS&lt;/description&gt;</line>
					<line>&lt;version&gt;${update.xml.componente.version}&lt;/version&gt;</line>
					<line>&lt;rootPath&gt;..&lt;/rootPath&gt;</line>
					<line>&lt;packageInfo&gt;</line>
					<line>&lt;allowRollback&gt;false&lt;/allowRollback&gt;</line>
					<line>&lt;type&gt;full&lt;/type&gt;</line>
					<line>&lt;/packageInfo&gt;</line>
					<line>&lt;/application&gt;</line>
				</lines>
			</file>
		</files>
	</configuration>
	<executions>
		<execution>
			<id>write-text-files</id>
			<phase>prepare-package</phase>
			<goals>
				<goal>write-text-files</goal>
			</goals>
		</execution>
	</executions>
</plugin>










Plugins compiler e geração do jar
<plugin>
	<artifactId>maven-compiler-plugin</artifactId>
	<version>3.3</version>
	<configuration>
		<source>1.7</source>
		<target>1.7</target>
	</configuration>
</plugin>
<plugin>
	<artifactId>maven-jar-plugin</artifactId>
	<version>2.6</version>
	<configuration>
		<archive>
			<addMavenDescriptor>true</addMavenDescriptor>
			<manifest>
				<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
			</manifest>
		</archive>
	</configuration>
	<executions>
		<execution>
			<phase>package</phase>
		</execution>
	</executions>
</plugin>


Move o arquivo .jar para diretório de build
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-dependency-plugin</artifactId>
	<executions>
		<execution>
			<id>copy-artifact</id>
			<phase>package</phase>
			<goals>
				<goal>copy</goal>
			</goals>
			<configuration>
				<artifactItems>
					<artifactItem>
						<groupId>${project.groupId}</groupId>
						<artifactId>${project.artifactId}</artifactId>
						<version>${project.version}</version>
						<type>jar</type>
						<overWrite>true</overWrite>
						<outputDirectory>${project.build.directory}/lib</outputDirectory>
					</artifactItem>
				</artifactItems>
				<overWriteReleases>false</overWriteReleases>
				<overWriteSnapshots>true</overWriteSnapshots>
			</configuration>
		</execution>
		<execution>
			<id>unpack</id>
			<goals>
				<goal>unpack</goal>
			</goals>
			<configuration>
				<artifactItems>
					<artifactItem>
						<groupId>linx</groupId>
						<artifactId>${linx-storex-pos-standard.artifactId}</artifactId>
						<version>${linx-storex-pos-standard.version}</version>
						<outputDirectory>${basedir}/configuracao/padrao/servidor-configuracao/xml/</outputDirectory>
						<includes>**/*.xml</includes>
					</artifactItem>
				</artifactItems>
				<overWriteReleases>false</overWriteReleases>
				<overWriteSnapshots>true</overWriteSnapshots>
			</configuration>
		</execution>
	</executions>
</plugin>


Prepara o arquivo XML com parametrizações
<plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>xslt-maven-plugin</artifactId>
	<executions>
		<execution>
			<id>merge-faces-config</id>
			<phase>package</phase>
			<goals>
				<goal>transform</goal>
			</goals>
			<configuration>
				<xslFile>${basedir}/configuracao/padrao/servidor-configuracao/xml/mergeConfig.xsl</xslFile>
				<srcDir>${basedir}/configuracao/padrao/servidor-configuracao/xml/</srcDir>
				<destDir>${project.dist.dir}/</destDir>
				<srcIncludes>linx-storex-pos-custom-config.xml</srcIncludes>
				<fileNameRegex>linx-storex-pos-custom-config</fileNameRegex>
				<fileNameReplacement>${project.artifactId}-config-${project.version}</fileNameReplacement>
			</configuration>
		</execution>
	</executions>
</plugin>



Plugin que gera o arquivo final PKG
<plugin>
	<artifactId>maven-antrun-plugin</artifactId>
	<version>1.7</version>
	<executions>
		<execution>
			<id>cria-estrutura-pkg</id>
			<phase>package</phase>
			<configuration>
				<target>
					<!-- Gerando o bootstrap.jar -->
					<property name="version" 							value="${project.version}" />
					<property name="project.build.directory"			value="${project.build.directory}" />
					<property name="compilacao.libs"					value="${project.build.directory}/lib" />
					<property name="compilacao.completo.build"			value="${project.build.directory}/classes" />
					<property name="storex-pos-custom.artifactId"		value="${project.artifactId}" />
					<property name="storex-pos-custom.version"			value="${project.version}" />
					<property name="storex-pos-gui-custom.artifactId"	value="${pos-gui-custom.artifactId}" />
					<property name="storex-pos-gui-custom.version"		value="${pos-gui-custom.version}" />
					<property name="storex-pos-standard.artifactId"		value="${linx-storex-pos-standard.artifactId}" />
					<property name="storex-pos-standard.version"		value="${linx-storex-pos-standard.version}" />
					<property name="application.bin" 					value="../bin/" />
					<property name="application.config" 				value="../config/" />
					<property name="bootstrap.version"					value="${bootstrap.version}" />
					<ant antfile="build/build-bootstrap.xml" />

					<!-- INICIO DA GERACAO DO PKG -->

					<!-- OVERWRITE -->

					<!-- Copiando as libs -->
					<copy
						todir="${project.build.directory}/${pkg.dir.name}/${pkg.overwrite.path}/lib">
						<fileset dir="${project.build.directory}/lib/">
							<include name="**"/>
							<exclude name="${jython.name}-${jython.version}.jar"/>
						</fileset>
					</copy>
					
					<!-- Renomeando lib do bootstrap -->
					<move file="${project.build.directory}/${pkg.dir.name}/${pkg.overwrite.path}/lib/linx-bootstrap-${bootstrap.version}.jar"
							tofile="${project.build.directory}/${pkg.dir.name}/${pkg.overwrite.path}/lib/linx-bootstrap.jar" />

					<!-- Copiando os resources -->
					<copy
						todir="${project.build.directory}/${pkg.dir.name}/${pkg.overwrite.path}/bin/statemachine">
						<fileset dir="${project.resources.dir}/statemachine/"
							includes="**" />
					</copy>

					
					<!-- Versão PDV -->
					<echo file="${project.build.directory}/${pkg.dir.name}/${pkg.overwrite.path}/bin/versaoPDV.dat" message="${update.xml.componente.version}" />

					<!-- Copiando a estrutura de dominios -->
					<copy
						todir="${project.build.directory}/${pkg.dir.name}/${pkg.overwrite.path}/bin/dominios">
						<fileset dir="${project.resources.dir}/configuracao/dominios/"
							includes="**" />
					</copy>

					</target>
					
					</configuration>
			<goals>
				<goal>run</goal>
			</goals>
		</execution>
		
		<execution>
			<id>zipando-pkg</id>
			<phase>package</phase>
			<configuration>
				<target>
					<!-- Copiando e gerando o PKG -->
					<zip
						destfile="${project.build.directory}/${pkg.dir.name}.zip"
						basedir="${project.build.directory}/${pkg.dir.name}" />
					<copy file="${project.build.directory}/${pkg.dir.name}.zip"
						tofile="${project.dist.dir}/${project.build.finalName}.pkg" />
					<delete
						file="${project.build.directory}/${pkg.dir.name}.zip" />
					<!-- FIM DA GERACAO DO PKG -->
				</target>
			</configuration>
			<goals>
				<goal>run</goal>
			</goals>
		</execution>
	</executions>
</plugin>




  • Sem rótulos