Tuesday, October 16, 2018

Modular Projects no NetBeans 9.0

NetBeans 9 é a primeira release desde que a IDE passou a fazer parte da família Apache, cujo nome oficial agora é Apache NetBeans.

O NetBeans 9 também é a primeira versão desta IDE a conter suporte para o sistema de modularização da plataforma java, recurso que foi incluido a partir da versão 9 do java. Um módulo na plataforma Java consiste em:
  • Uma coleção de pacotes
  • Uma lista de quais pacotes estarão acessíveis para outros módulos
  • Uma lista de todos os módulos dos quais o módulo atual depende
Um módulo, portanto, pode controlar seletivamente quais pacotes estão disponíveis, isso reforça o encapsulamento e o gerenciamento de dependências, evitando problemas recorrentes na configuração do class path de seu projeto, tais como classes duplicadas ou não encontradas (ClassNotFoundException).



Java Modular Project

O NetBeans 9 apresenta uma nova opção de projeto, que é o Java Modular Project.
Caso queira modularizar sua aplicação, você deve escolher essa opção ao criar um novo projeto. 


Vamos criar um novo Java Modular Project que faz uso do módulo java.xml.bind, popularmente conhecido como JAXB API, ou seja, nosso projeto de exemplo converte uma classe java em um arquivo xml (você pode conferir todos os módulos disponíveis no javadoc do Java 10). Clique em Next e dê o nome ao novo projeto de JavaModular.

Clique com o botão direito na raiz do projeto JavaModular, navegue por new / module:


Dê o nome ao novo módulo de modular.test. (nomes de módulo devem ser globalmente únicos, a melhor forma de garantr isso é utilizar a mesma abordagem para nomeação de pacotes). O NetBeans já cria automaticamente o arquivo de configuração obrigatório em todos os módulos, chamado de module-info.java.

Clique com o botão direito no módulo que você acabou de criar e adicione um novo pacote chamado com:


Repare na estrutura do projeto. No pacote com vamos criar a classe Pais, que será convertida em um arquivo XML:
package com;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Pais {
 
 @XmlElement
 private String nome;
 @XmlElement
 private double area;

 public Pais() {
 }

 public Pais(String nome, double area) {
  this.nome = nome;
  this.area = area;
 }
    //getters e setters...

Ao criar as delcarações de import para os pacotes javax.xml, ocorre um erro de compilação, package javax.xml.bind.annotation is not visible. Isso porque esses pacotes estão em um módulo separado. Precisamos declarar explicitamente no arquivo module-info que nosso módulo modular.test precisa desses pacotes, os quais pertencem ao módulo java.xml.bind. Para isso utilizamos a palavra chave requires dentro do arqivo de configuração do módulo:

module modular.test{
 
    requires java.xml.bind;

}

Agora no pacote com crie a classe Main na qual instanciaremos um objeto da classe Pais:
package com;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

public class Main {

 public static void main(String[] args) throws JAXBException {
 
  Pais brasil = new Pais("Brasil", 8_600_000);
  JAXBContext context = JAXBContext.newInstance(Pais.class);
  Marshaller m = context.createMarshaller();
  m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
  m.marshal(brasil, System.out);
 }
}

Até aqui vimos claramente como a modularização reforça o encapsulamento. Um módulo só pode acessar pacotes explicitamente exportados por outros módulos, ou seja, só conseguimos usar as classes do pacote java.xml.bind porque o módulo java.xml exporta tais pacotes. Por exemplo, se quisermos que o pacote que acabamos de criar com esteja disponível para uso em outros módulos, então no arquivo module-info adicionamos a declração exports para esse pacote:

 exports com;

Reflection API em Módulos

Outro ponto interessante a notar é que frameworks de mapeamento como o JAXB, que estamos usando neste exemplo, ou o JPA, que mapeia classes Java para tabelas no banco de dados, entre outros,  utilizam a API Reflection para fazer o mapeamento das propriedades das classes, mesmo que essas propriedades sejam privadas. Em um ambiente modular, tentar acessar campos privados via reflection não é 100% garantido. Sim, isso significa que um sistema desenvolvido no Java 8 (ou mais antigo) que faz uso de APIs como JAXB, JPA ou outros frameworks que utilizam extensivamente a API Reflection, pode não rodar no ambiente Java 9 (ou mais novo).

Tente executar a classe Main e comprove. Uma exceção é lançada porque o JAXB tenta acessar os campos privados da classe Pais via reflection.

Para liberar o acesso via reflection não basta exportar sua classe, é necessário utilizar a declaração opens para determinada classe ou pacote. O arquivo module-info portanto deve ficar como segue:
module modular.test {
    exports com;
    requires java.xml.bind;
    opens com;
}

Agora sim podemos executar a classe Main. Ela imprime na tela a o objeto Pais no formato xml:
<?xml version="1.0" encoding="UTF-8"?>
<pais>
    <nome>Brasil</nome>
    <area>8600000.0</area>
</pais>

         

Monday, October 1, 2018

AWS-EC2: Acessando Windows a partir do Linux

Após criar e lançar uma instância Windows na AWS, para acessá-lá a partir de um Linux, os seguintes passos são requeridos:

  1. Adicionar no security group da instância Windows uma regra interna (inbound rule) para permitir acesso remoto usando o protocolo RDP (Remote Desktop Protocol);
  2. Ainda no security group, liberar a origem do acesso remoto para seu próprio IP ou qualquer outro;
  3. Na máquina Linux instalar o software Remmina para o acesso remoto.

Configurando o Security Group

Por padrão, Security Groups não permitem acesso remoto pelo protocolo RDP. Você precisa criar uma regra interna liberando esse processo a partir de um ou qualquer endereço IP.

No console de administração da AWS, edite o Secutity Group da instância Windows para a qual você quer liberar o acesso remoto. Como na imagem abaixo, na combobox type selecione RDP e em source, qualquer IP. Salve esta configuração.



Instalando e configurando Remmina

Livre de licensas, Remmina é um cliente de desktop remoto para Linux semelhante ao TeamViewer. O Remmina suporta os protocolos  RDP, VNC, NX, XDMCP, SSH e Telepathy; ele também mantém a lista dos desktops remotos que você acessou.

Para instalar o Remmina execute
  sudo apt install remmina
    
Algumas versões estão vindo sem o protocolo UDP, se for o seu caso, ao invés da opção acima, você pode tentar instalar o remmina com o seguinte comando:

sudo apt-get install remmina remmina-plugin-vnc remmina-plugin-rdp

Após instalar, abra o remmina e clique em new:



Na janela que vai abrir, você deve informar os dados de acesso da instância Windows:

  • Em protocol, selecione RDP
  • Em server, coloque o IP público da instância Windows e o número da porta 3389, no formato <numero_ip_publico>:3389
  • O nome do usário, geralmente Administrator
  • A senha de acesso
  • E o DNS público da instancia, algo como ec2-177-29-159-173.sa-east-1.compute.amazonaws.com


Na aba advanced, você encontra algumas opções Qualidade, Som. Qualidade de imagem menor, pode resultar em um ganho de velocidade. Se preferir, pode deixar como está:




Na aba SSH, mantenha desmarcada e opção Enable SSH tunel:


Dê um nome para sua conexão, no meu caso AWS Windows 2016, e salve-a. 

Agora selecione a conexão que você acabou de criar, botão direito do mouse, e clique em conectar:


O remmina exibe o desktop remoto com o qual você acabou de se conectar: