Labs SD

Perguntas e respostas sobre os Laboratórios e o Projecto


Dúvidas 2ª Parte do Projecto

  1. Pergunta: É possível modificar o WSDL para acrescentar uma operação de atualização de estado de um transporte?

    Resposta: Sim, é possível. Devem só ter a precaução de não quebrar a compatibilidade do contrato, ou seja, as operações já existentes devem ser especificadas sem alteração.
    Sugere-se que se mude o nome ao ficheiro do contrato para broker.2_0.wsdl.


  2. Pergunta: Como se podem representar dados binários em texto?

    Resposta: Podem usar codificação de base 64 para transportar dados binários em texto.

    Sugerimos a utilização das seguintes funções:

    import static javax.xml.bind.DatatypeConverter.parseBase64Binary;
    import static javax.xml.bind.DatatypeConverter.printBase64Binary;
    


  3. Pergunta: É necessário proteger as comunicações entre clientes e broker, e com o UDDI?

    Resposta: Não é necessário. O que é pedido é para proteger a comunicação entre broker (transporter-client) e transporter (server).


  4. Pergunta: É necessário replicar o UDDI?

    Resposta: Pode-se considerar o UDDI como sendo 100% disponível, não sendo necessário efectuar a sua replicação.


  5. Pergunta:[BOA PRÁTICA] Como partilhar código entre vários programas?

    O servidor e o cliente devem partilhar o mínimo de código possível.

    No entanto, em alguns casos faz sentido partilhar código (ex. UDDINaming, Handlers, etc).

    Nestes casos a melhor prática é criar módulos Maven autónomos, com os respectivos testes, que podem depois ser publicados (mvn install) e usados como dependências através das coordenadas (groupId, artifactId, e version).

    Esta separação em módulos promove também o desenvolvimento paralelo de código de diferentes componentes do projeto, dado que diferentes membros da equipa podem estar a trabalhar simultaneamente em diferentes partes do projeto.


  6. Pergunta: Como se podem gerar as chaves e certificados digitais? [atualizada]

    Resposta: Os pares de chaves das entidades devem ser gerados manualmente, antes do início do funcionamento da comunicação entre servidores.

    Para gerar os certificados podem usar as ferramentas keytool e openssl tal como exemplificado neste script.

    Exemplo de resultado.
    Documentação: Creating a Sample CA Certificate, Signing Certificates With Your Own CA

    O script automaticamente importa os certificados para as respectivas keystores, ou seja, todas as entidades têm na sua keystore o certificado da CA, o seu próprio certificado e a sua chave privada. A CA pode simplesmente guardar os certificados das outras entidades em ficheiros individuais ou ter a sua própria keystore os certificados de todas as entidades, o seu próprio certificado e a sua chave privada.

    Resumidamente, o que cada entidade deve fazer quando pretende autenticar uma mensagem é:

    • pedir (caso não tenha pedido antes) o certificado do emissor da mensagem (emissor.cer);
    • verificar se esse certificado (emissor.cer) foi devidamente assinado pelo CA usando o certificado da CA (ca-certificate.cer) que está guardado na sua keystore (recetor.jks)
    • usar o certificado do emissor (se for válido) para verificar a assinatura digital da mensagem;

  7. Pergunta: O que é um ficheiro CSR?

    Resposta: Um ficheiro CSR é um 'Certificate Signing Request' e serve para pedir a uma CA para assinar uma chave pública.
    Depois de gerados e assinados os certificados, os CSR já não são necessários (e podem ser eliminados).


  8. Pergunta: O que deve constar do relatório?

    Resposta: Consultar a informação publicada sobre o relatório.


  9. Pergunta: As instruções de instalação devem ser atualizados para a segunda parte do projeto?

    Resposta: Sim, o ficheiro README.md deve ser atualizado com instruções tendo em conta as funcionalidades pedidas de segurança e de tolerância a faltas.


  10. Pergunta: Porque é que algumas chaves têm que ser distribuídas manualmente antes do arranque do sistema?

    Resposta: O sistema, para ser seguro, necessita de ter um ponto de partida para a confiança (uma trust root, raíz de confiança). Só depois é seguro trocar chaves entre servidores, desde que certificadas, cujas assinaturas podem ser verificadas com as chaves que fazem parte da trust root.


Dúvidas 1ª Parte do Projecto

  1. Pergunta: É necessário entregar instruções de instalação?

    Resposta: Sim, é necessário completar o ficheiro README.md com instruções de instalação do projecto que possam ser seguidas nas máquinas dos laboratórios.


  2. Pergunta: Para que serve o transporter-ws-cli?

    Resposta: O projeto transporter-ws-cli serve para:

    • Gerar os stubs do transporter-ws
    • Conter os testes de integração (...IT) do transporter-ws
    • Encapsular criação de stubs e invocações remotas a um servidor transporter-ws dentro da classe TransporterClient.
      Código (por exemplo, no broker-ws) que queira invocar serviços remotos de uma transportadora poderia, por esta ordem:
      • Obter os endpoints das transportadoras a partir do jUDDI: Collection endpoints = uddiNaming.list("UpaTransporter%");
      • Instanciar um TransporterClient por cada transportadora que se queira invocar remotamente (exemplo): TransporterClient tc = new TransporterClient(specificEndpoint)


  3. Pergunta: O que deve fazer a classe ...ClientApplication?

    Resposta: Esta classe deve ter um método static main que serve apenas para fazer uma invocação simples do servidor. Sugere-se que faça um ping().


  4. Pergunta: Que testes com mocks fazem sentido no código de SD?

    Resposta: Na primeira entrega de SD os mocks poderão ser úteis para permitir testes unitários (...Test) em objetos que dependam de serviços remotos.
    Concretizando, os mocks permitirão simular os objetos que representam o UDDI e as Transportadoras.


  5. Pergunta: Em que consiste o retorno da operação requestTransport()?

    Resposta: O retorno deve ser o identificador do transporte, que pode ser usado mais tarde para consultar o estado do transporte.


  6. Pergunta: De que forma se pode implementar a simulação do estado do Job na Transportadora?

    Resposta: Sugere-se a consulta da documentação das seguintes classes:

    A atualização pode também ser feita só quando necessário, ou seja, as transições podem ser despoletadas nas operações que consultam estados dos Jobs.

  7. Pergunta: Como se deve comportar e testar o seguinte web service (do transporter-ws) quando o preço dado é 0 ou 1?
    @Override
    public JobView requestJob(String origin, String destination, int price)

    Resposta: Este caso extremo não será testado. É válido que uma transportadora, quando recebe um pedido com preço 0 ou 1, proponha preço 0.
    Restantes valores de preço deverão obedecer ao especificado no enunciado do projeto.


  8. Pergunta: Quando uma transportadora faz uma proposta, existe um valor máximo para o preço?

    Resposta: Quando uma transportador está num caso em que deve fazer uma proposta (ver regras descritas no enunciado - par-ímpar, etc.)
    não é necessário limitar o valor da proposta máxima gerada.
    No entanto, se o quiserem fazer, podem estipular um valor máximo que faça sentido, como 1000, por exemplo.


  9. Pergunta: O que deve o Broker retornar ao seu cliente no método requestTransport() no caso de todas as transportadoras devolverem null ?

    Resposta: O Broker deve passar o transporte para o estado FAILED e deve lançar UnavailableTransportFault.


  10. Pergunta: E quando deve o Broker retornar ao seu cliente no método requestTransport a exceção UnavailablePriceTransportFault ?

    Resposta: O Broker deve atirar a exceção referida quando recebe propostas, mas nenhuma abaixo do preço pedido pelo cliente.


  11. Pergunta: O Broker deve registar-se no UDDI?

    Resposta: Sim e deve chamar-se UpaBroker, tal como é referido no enunciado.


Dúvidas Java/Maven/Eclipse

  1. Pergunta: Existe algum atalho para a página de laboratórios de SD?

    Resposta: Sim, existe este: http://tinyurl.com/leic-sod


  2. Pergunta: Para onde devem ser enviadas as dúvidas sobre o projecto?

    Resposta: As perguntas devem ser enviadas para o endereço correspondente ao curso do aluno:
    leti-sod@disciplinas.tecnico.ulisboa.pt
    leic-tagus-sod@disciplinas.tecnico.ulisboa.pt
    leic-alameda-sod@disciplinas.tecnico.ulisboa.pt


  3. Pergunta:[IMPORTANTE] Existe alguma restrição sobre a directoria de instalação do software?

    Resposta: Sim, infelizmente devido a diversos bugs em ferramentas, o software não funciona corretamente em pastas cujo caminho tenha espaços e/ou caracteres acentuados (sobretudo em Windows).
    Exemplos de pastas problemáticas:

    • C:\program files
    • C:\users\André
    • C:\users\Alice Silva

    Dado este problema a sugestão é instalar o software numa pasta como C:\java\.


  4. Pergunta: Devem-se instalar exatamente as versões pedidas ou podem ser outras?

    Resposta: Sim, devem procurar instalar as versões pedidas de forma a terem um ambiente igual (ou o mais parecido possível) com o ambiente de referência (dos laboratórios).
    Se não for possível encontrar a versão exata, podem instalar a versão mais próxima disponível.

    Existem riscos em ter diferenças mas, na maior parte dos casos, não deverão ser impeditivos da realização do projeto.
    Em todo o caso, ao testar os exemplos das aulas será possível detetar se há ou não diferenças relevantes.


  5. Pergunta: Como confirmar se estou a usar as versões certas das ferramentas?

    Resposta: Abrir uma consola e executar os seguintes comandos:

    $ java -version
    
    $ javac -version
    
    $ mvn -version
    
    Start Eclipse, go to "Help" menu, select "About Eclipse"


  6. Pergunta: Como confirmar se o PATH está correcto?

    Resposta: Abrir uma consola Linux e executar

    $ echo $PATH
    
    Abrir uma consola Windows e executar
    $ echo %PATH%
    


  7. Pergunta: Porque é que o meu Mac não reconhece o endereço localhost?

    Resposta: As seguintes instruções poderão resolver o problema:
    http://www.codepotato.co.uk/2012/07/25/enabling-localhost-on-os-x-mountain-lion/


  8. Pergunta: O meu nome de utilizador tem acentos ou espaços e preciso de mudar a localização do repositório local Maven. Como se faz?

    Resposta: O repositório local do Maven é a pasta onde são guardadas todas as dependências obtidas pelo Maven.

    Por omissão, a localização do repositório local é:
    ~/.m2 (Unix/Mac)
    C:\Users\Username\.m2 (Windows)

    Para alterar a configuração, editar o ficheiro conf\setting.xml que está na pasta de instalação do Maven (tipicamente apontada pela variável de ambiente M2_HOME).

    Mais informação

    Não esquecer também de atualizar a configuração do repositório Maven no Eclipse. Aceder a Window - Preferences - Maven - User Settings e indicar a nova configuração.


  9. Pergunta: Como posso consultar o effective POM de um projeto Maven?

    Resposta: O effective POM é o resultado da combinação do POM do projeto com os valores das propriedades por omissão. É útil para perceber todas as definições que são assumidas pela ferramenta, como valores de propriedades, por exemplo.

    Pode-se consulta através do seguinte comando:

    $ mvn help:effective-pom
    


  10. Pergunta: Existe forma de consultar a árvore de dependências de um projeto Maven?

    Resposta: Sim, através do seguinte comando:

    $ mvn dependency:tree
    


  11. Pergunta: Como remover o aviso de character encoding do Maven?

    Resposta: Acrescentar a seguinte configuração ao pom.xml:

        ...
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            ...
    


  12. Pergunta: Como remover o aviso "Warning: killAfter is now deprecated" do Maven?

    Resposta: Para remover este aviso (inofensivo) pode-se acrescentar a seguinte configuração ao pom.xml:

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            ...
              <configuration>
                <killAfter>-1</killAfter>
                ...
              </configuration>
          </plugin>
    


  13. Pergunta: Como definir a versão do Java considerada pelo Maven?

    Resposta: Acrescentar a seguinte configuração ao pom.xml:

        ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            ...
            <configuration>
               <source>1.8</source>
               <target>1.8</target>
               ...
            </configuration>
        </plugin>
    
    Mais informação na seguinte página: http://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html


  14. Pergunta: Qual a diferença entre exec:java e appassembler ?

    Resposta: mvn exec:java corre dentro do maven e tem os argumentos definidos no pom.xml com bons valores por omissão (opção preferida para desenvolvimento).
    mvn package appassembler:assemble corre de forma autónoma do Maven e necessita que sejam indicados os argumentos (opção preferida para demonstração)

    target/bin/appassembler/... .bat arg0 arg1 ...
    Via Eclipse também se pode correr, depois de compilado, definindo-se os argumentos nas "Run Configurations".


  15. Pergunta:[BOA PRÁTICA] É possível criar módulos Maven para partilha de código?

    Resposta: Sim, é possível.

    Para o fazer, criar um projeto à parte (ex. my-library).
    No pom.xml, definir as coordenadas groupId (ex. example), artifactId (ex. my-library) e version (ex. 1.0-SNAPSHOT).

    Para disponibilizar o módulo no repositório Maven local (~/.m2), fazer: mvn install.

    Para usar o módulo noutro projeto, basta acrescentar a dependência, indicando as coordenadas groupId, artifactId e version tal como se faz em relação a módulos que estão no repositório Maven central (ex. junit, junit, 4.12).


  16. Pergunta: Como executar o programa Java directamente, sem ser através do Maven ou do Eclipse?

    Resposta: Caso existam problemas no processamento de entradas e saídas de um programa (o que é comum acontecer com as aplicações de consola que são executadas a partir de outra ferramenta) sugere-se a seguinte solução, que passa por usar o plug-in appassembler para construir ficheiros de lançamento da aplicação, para Windows e Linux.


  17. Pergunta: Como executar o plug-in appassembler de forma automática na fase install?

    Resposta: Acrescentar a seguinte configuração ao pom.xml:

        ...
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>appassembler-maven-plugin</artifactId>
            <version>1.9</version>
            <executions>
                <execution>
                    <phase>install</phase>
                    <goals>
                        <goal>assemble</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
    

  18. Pergunta: É possível ter POMs hierárquicos? Como se usam?

    Resposta: O Maven tem dois conceitos hierárquicos: modules e parent.

    <project ...>
        <!-- the parent relation -->
        <parent>
            <groupId>example</groupId>
            <artifactId>parent</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </parent>
        <artifactId>module1</artifactId>
        <!-- the modules -->
        <modules>
            <module>submodule1</module>
            <module>submodule2</module>
        </modules>
    </project>
    

    A relação parent indica que configurações de propriedades, repositórios e plug-ins devem ser herdadas do projeto pai.

    Um module indica que o subprojeto deve ser incluído no processamento do ciclo de vida do projeto de topo.


  19. Pergunta: Como executar testes de integração (classes terminadas em IT)?

    Resposta: Caso não exista ainda a definição (definida no pom pai, por exemplo) será necessário adicionar a configuração do plug-in para testes de integração:

                <plugin>
                    <artifactId>maven-failsafe-plugin</artifactId>
                    <version>2.18.1</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>integration-test</goal>
                                <goal>verify</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
    

  20. Pergunta: Como posso ler ficheiros (recursos/resources) da aplicação?

    Resposta: Colocar os ficheiros em src/main/resources (ou em src/test/resources para testes).
    Fazer mvn process-resources e confirmar que ficheiros adicionados são processados e copiados para a pasta target.
    Se se pretender copiar propriedades definidas no Maven para estes ficheiros é possível usar a opção filter. (usando a etiqueta project/build/resources ou project/build/testResources no pom.xml).

    <project ...
      ...
      <build>
        <resources>
          <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
          </resource>
        </resources>
        <testResources>
          <testResource>
            <directory>src/test/resources</directory>
            <filtering>true</filtering>
          </testResource>
        </testResources>
        ...
    

    Depois de configurado o pom.xml, no código, é possível aceder a um java.io.InputStream para ler os dados binários.

        ...
    
        InputStream is = this.getClass().getResourceAsStream("/file");
    
        ...
    
    Adicionalmente, a classe java.io.ByteArrayOutputStream pode ajudar a lidar com dados de tamanho variável.


  21. Pergunta: Como converter de java.util.Date para javax.xml.datatype.XMLGregorianCalendar? E ao contrário?

    Resposta: De XMLGregorianCalendar para Date:

    
        Date d = xgc.toGregorianCalendar().getTime();
    
    
    De Date para XMLGregorianCalendar:
    
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTime(d);
        XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
    
    


  22. Pergunta: Como fazer cálculos com datas?

    Resposta: Usando a classe Calendar, por exemplo.

    
        Date date = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, 10);
        Date newDate = cal.getTime();
    
    


  23. Pergunta: Como resolver o seguinte problema na compilação:

    Exception in thread "main" java.lang.Error: Unresolved compilation problems

    Resposta: As classes foram corrompidas por diferentes compiladores em simultâneo (por ex. Eclipse e Maven).
    Para corrigir ir a Eclipse -> Menu 'Project', 'Clean', 'clean all projects". Depois, correr mvn clean.


  24. Pergunta: Como posso gerar um mock que implementa duas interfaces em simultâneo (ex. MyPortType e BindingProvider) ?

    Resposta: Consultar a seguinte página do tutorial de JMockit: Mocking multiple interfaces at the same time.


  25. Pergunta: Nos computadores dos laboratórios do Taguspark em Windows, pode ser necessário instalar mais algum plugin em Eclipse?

    Resposta: Poderá ser necessária a instalação de plugins adicionais se não estiver a conseguir correr o código em Windows 10 nos computadores do Taguspark, para além do que é pedido no guia de software.
    Se estiver a ter problemas, adicione e instale todos os Connectors do repositório bitstrings.org m2e Connectors.
    - No Eclipse:

    • Help -> Install New Software... -> Botão "Add..."
      Preencha com os seguintes valores: [Name: m2e - Connectors] e [Location: http://bitstrings.github.com/m2e-connectors-p2/releases]
    • Work with: m2e - Connectors
      Instalar tudo desse repositório.
    • Window -> Preferences -> Maven -> Discovery -> Botão "Open Catalog"
      Escolher e instalar os seguintes:
      • m2e - Maven Integration for Eclipse
      • m2e - slf4j over logback logging
      • m2e axistools
      • m2e connector for maven-remote-resources-plugin
      • m2e extension for the org.basepom property-helper plugin
      • Maven Development Tools
      • Plexus Metadata Generation
      • Takari Build Lifecycle Support
      • Takari Usage Statistics Reporter
    • Com estes plugins adicionais, já deverá conseguir compilar e executar corretamente os vários exercícios no Eclipse em Windows 10 nos laboratórios do Taguspark.


  26. Pergunta: Consigo compilar e executar os exercícios de código com o Maven no terminal, mas como o faço dentro do Eclipse?

    Resposta: O Eclipse, depois de instalado seguindo o guia, consegue invocar ações de Maven.
    Para um projeto Maven no Eclipse, é necessário criar configurações de Maven Build, como é descrito em seguida:
    Package Explorer: Right-click no nome do projeto -> Run As -> Run Configurations... -> Maven Build -> New launch configuration

    Configuração de Maven goals em Eclipse
    Especificando em Base directory: o caminho para o diretório do projeto e em Goals: a sequência de ações Maven a desempenhar, pode clicar em Apply e a partir dai poderá executar com esta parametrização através do botão Run.
    Neste exemplo específico, ao clicar em Run serão executados para o projeto hello-ws-cli_juddi os comandos:
    • mvn generate-sources
    • mvn compile
    • mvn exec:java


  27. Pergunta: Já segui todas as instruções no guia de software mas mesmo assim o Eclipse não consegue compilar código Java, o que poderá ser o problema?

    Resposta: É possível que, apesar do JDK estar instalado, o Eclipse esteja a apontar para um módulo JRE (Java Runtime Environment), que apenas permite executar programas Java mas não compilar.
    Para resolver esta questão, por exemplo em Windows, é necessário seguir os seguintes passos:
    Ir a Window -> Preferences -> Java -> Installed JREs -> Add...
    Indicando o diretório do JDK instalado (seguindo o guia deverá chamar-se jdk1.8.0_72), deve obter o seguinte resultado:

    Adição do JDK aos Installed JREs

    Carregue em Apply, OK. A partir de agora, o Eclipse está configurado para invocar as ferramentas de compilação de Java, tais como o javac.


  28. Pergunta: Já configurei o Eclipse para usar o JDK 8, mas mesmo assim quando importo um projeto Maven, o Eclipse assume que é para usar J2SE5 ou outra qualquer versão estranha, como corrigir isto?

    Resposta: Para assegurar que o projeto Maven funciona como esperado, recomenda-se dar uma indicação explícita da versão de JDK a usar para o projeto.
    Para resolver esta questão, é necessário especificar a versão no pom.xml do projeto, inserindo as tags maven.compiler.source e maven.compiler.target aninhadas na tag properties.
    Exemplo concreto, aplicado ao pom.xml do projeto hello-ws-cli_juddi:

    ...
    </dependencies>

    <properties>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <mainclass>example.cli.HelloClient</mainclass>
    <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target>
    ...
    </properties>

    <build>
    ...


  29. Pergunta: Ao executar o Maven no Ubuntu dá-me o seguinte erro:

    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building java-app 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    Downloading: https://repo.maven.apache.org/maven2/org/codehaus/mojo/exec-maven-plugin/1.4.0/exec-maven-plugin-1.4.0.pom
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD FAILURE
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 0.629 s
    [INFO] Finished at: 2016-02-24T11:30:56+00:00
    [INFO] Final Memory:8M/110M
    [INFO] ------------------------------------------------------------------------
    [ERROR] Plugin org.codehaus.mojo:exec-maven-plugin:1.4.0 or one of its dependencies could not be resolved: Failed to read artifact descriptor for org.codehaus.mojo:exec-maven-plugin:jar:1.4.0: Could not transfer artifact org.codehaus.mojo:exec-maven-plugin:pom:1.4.0 from/to central (https://repo.maven.apache.org/maven2): java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty -> [Help 1]
    [ERROR]
    [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
    [ERROR] Re-run Maven using the -X switch to enable full debug logging.
    [ERROR]
    [ERROR] For more information about the errors and possible solutions, please read the following articles:
    [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginResolutionException

    Como resolvo este problema?

    Resposta: Executando o seguinte comando na shell:

    sudo /var/lib/dpkg/info/ca-certificates-java.postinst configure

  30. Pergunta: Como resolver corrigir a versão do Java na RNL para Java 1.8? Erro:

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) 
    on project java-app: Fatal error compiling: invalid target release: 1.8 -> [Help 1]

    Resposta: Executando o seguinte comando na shell:

    export JAVA_HOME=/usr/lib64/jdk1.8.0_72/


  31. Pergunta: No Eclipse, quando tento compilar o projeto via Maven, obtenho o seguinte erro (por exemplo, no transporter-ws):

    [ERROR] Failed to execute goal org.jvnet.jax-ws-commons:jaxws-maven-plugin:2.3:wsimport (default) on project transporter-ws: 
    Execution default of goal org.jvnet.jax-ws-commons:jaxws-maven-plugin:2.3:wsimport failed: String index out of range: -1 -> [Help 1]
    
    Como faço para resolver este erro?

    Resposta: Poderá ser necessário atualizar a configuração do Maven dentro do Eclipse:
    Ir a Window -> Preferences -> Maven -> Installations, escolher a instalação com NAME com o valor "EMBEDDED"
    (possivelmente já estará com este valor) e depois escolher a instalação local (poderá ser necessário carregar em Add... e indicar
    o diretório da instalação do Maven conforme os passos executados no guia de software)

    Eclipse Maven installation choice.



Dúvidas Web Services

Dúvidas JAX-WS

  1. Pergunta: Como validar um ficheiro WSDL no Eclipse?

    Resposta: Na janela de 'Project explorer', carregar com o botão direito sobre o ficheiro WSDL. Escolher a opção 'validate' e verifique o resultado em 'Markers'.


  2. Pergunta: A ferramenta de geração de código a partir de WSDL não está a funcionar como esperado.

    Resposta: O wsimport pode fornecer pouca informação sobre o erro no WSDL.

    Nesse caso, confirme:

    • Se todos os parâmetros passados ao wsimport estão correctos, especialmente se a localização do WSDL é a correcta.
    • Usando a opção "Validate" do Eclipse, assegure-se que nenhum erro nem aviso é reportado.
    • Em alguns sistemas operativos, o wsimport não interpreta correctamente pathnames com espaços; assegure-se que o caminho completo do WSDL não tem espaços.
    • Assegure-se que, na secção binding do WSDL, o atributo "name" das fault é idêntico (incluindo correspondência maiúsculas/minúsculas) ao nome da message definidas para as excepções de cada operação. Este erro não é reportado pelo Eclipse, apesar de impedir a geração correcta dos stubs.
    • Execute o wsimport através da linha de comandos, pois aí poderá receber uma mensagem mais detalhada sobre o erro no WSDL.


  3. Pergunta: Porque é que o código Java gerado para uma operação recebe uma classe de argumento em vez dos parâmetros simples?

    Resposta: O JAX-WS tem diferentes estilos de geração de código Java a partir do WSDL.
    Caso o nome da 'operation', 'message' e 'element' sejam iguais no WSDL, o código Java é gerado no wrapper-style, ou seja, os parâmetros surgem individualmente na operação.
    Caso contrário, o código é gerado no bare-style e a operação recebe apenas um argumento, de uma classe gerada, que depois contém os argumentos que são lidos com gets.


  4. Pergunta: Ao tentar desenvolver um Web Service pela abordagem contract-first o WSDL publicado é diferente e foi (re)gerado automaticamente.

    Resposta: O atributo wsdlLocation deve estar correctamente definido e o WSDL deve ser incluído correctamente no pacote da aplicação.


  5. Pergunta: Sempre que o servidor lança uma exceção, o cliente recebe uma excepção do tipo javax.xml.ws.soap.SOAPFault e não o tipo definido no WSDL

    Resposta: A classe gerada para cada exceção definida no WSDL contém diferentes métodos construtores. No entanto, apenas um dos construtores permite que a exceção que é lançada remotamente seja recebida pelo cliente como uma exceção do tipo pretendido.

        ...
        public MyFault(String message, MyFaultType faultInfo)
        ...
    
    Apenas o construtor que recebe a faultInfo permite que o cliente possa reconhecer correctamente a exceção como sendo do tipo MyFault.


  6. Pergunta: No cliente como se define o endereço do Web Service?

    Resposta: Sim. O seguinte exemplo de código ilustra como:

        String endpointAddress = "http://...";
    
        BindingProvider bindingProvider = (BindingProvider) port;
        Map requestContext = bindingProvider.getRequestContext();
    
        // retrieve old address
        String oldEndpointAddress = (String) requestContext.get(ENDPOINT_ADDRESS_PROPERTY);
    
        // set new address
        requestContext.put(ENDPOINT_ADDRESS_PROPERTY, endpointAddress);
    


  7. Pergunta: Quando lanço o meu Web Service e invoco operações a partir do cliente, os argumentos chegam sempre a null ao serviço. O que se passa de errado?

    Resposta: Provavelmente a razão está no atributo endpointInterface da anotação @Webservice da classe que implementa o serviço. Certifique-se que endpointInterface refere a interface que foi gerada pelo wsimport (normalmente essa interface tem o nome que foi atribuído ao portType no WSDL do serviço).


  8. Pergunta: No Eclipse, como remover o aviso: Access restriction: The type 'WebService' is not API (restriction on required library 'C:\Program Files\Java\jre1.8.0_31\lib\rt.jar') sobre a anotação @WebService da classe HelloImpl.java?

    Resposta: É necessário atualizar a versão do JRE System Library associado ao projeto. No Eclipse, deve-se proceder da seguinte forma:

    1. Sobre as propriedades do projeto, selecionar Java Build Path e depois Libraries.
    2. Remover o JRE System Library.
    3. É necessário voltar a adicionar; Selecione Add Library e escolher JRE System Library.


  9. Pergunta:[IMPORTANTE] Ao tentar executar o meu cliente de Web Service, a invocação remota falha com um erro

    Cannot load WSDL from http://...

    Resposta: Um cliente JAX-WS necessita de carregar o WSDL para criar um novo ...Service. Podem consultar o código desta classe gerada para confirmar a dependência.

    Para minorar este problema, em vez de se ir buscar o WSDL diretamente ao servidor com HTTP, pode optar-se por aceder a um ficheiro.
    No pom.xml do exemplo abaixo, vai-se buscar o ficheiro WSDL à pasta do servidor (ws), que se assume estar ao lado da pasta do cliente (ws-cli).

    ...
          <plugin>
            <groupId>org.jvnet.jax-ws-commons</groupId>
            <artifactId>jaxws-maven-plugin</artifactId>
            <version>2.3</version>
            <executions>
              <execution>
                <goals>
                  <goal>wsimport</goal>
                </goals>
              </execution>
            </executions>
            <configuration>
              <!-- https://jax-ws-commons.java.net/jaxws-maven-plugin/wsimport-mojo.html -->
              <wsdlDirectory>${basedir}/../ws/src/main/resources</wsdlDirectory>
              <wsdlFiles>
                <wsdlFile>Calc.wsdl</wsdlFile>
              </wsdlFiles>
            </configuration>
    ...
    

    Em alternativa também se poderia copiar o ficheiro WSDL para ws-cli/src/main/resources

    Existe ainda a opção -clientjar da ferramenta wsimport. Infelizmente, esta opção não é diretamente suportada pelo plug-in JAX-WS do Maven. Existe uma forma de usar a opção -clientjar mas é pouco elegante e, por esta razão, não é recomendada a sua utilização.

  10. Pergunta: Como resolver o problema com o jaxws maven plugin "Exception in thread "main" java.lang.ClassCastException: java.lang.NoSuchMethodError " ?

    Resposta:

    ...
    Exception in thread "main" java.lang.ClassCastException: java.lang.NoSuchMethodError cannot be cast to java.lang.Exception
        at org.jvnet.jax_ws_commons.jaxws.Invoker.main(Invoker.java:87)
    ...
    
    Este problema ainda não está completamente diagnosticado. Felizmente apenas acontece dentro do Eclipse e não na linha de comando.

Dúvidas UDDI

  1. Pergunta: Como lançar o jUDDI+Tomcat em Linux nos computadores dos laboratorios?

    Resposta:

    1. Nos laboratórios da RNL, basta fazer: juddi-startup.
    1. Descarregar o JUDDI para a pasta /tmp.
    2. cd /tmp.
    3. wget http://disciplinas.tecnico.ulisboa.pt/leic-sod/2015-2016/download/juddi-3.3.2_tomcat-7.0.64_9090.zip
    4. unzip juddi-3.3.2_tomcat-7.0.64_9090.zip
    5. chmod +x /tmp/juddi-3.3.2_tomcat-7.0.64_9090/bin/*.sh
    6. /tmp/juddi-3.3.2_tomcat-7.0.64_9090/bin/startup.sh


  2. Pergunta: Ao tentar lançar o jUDDI+Tomcat, obtenho um erro: BASEDIR not found
    Qual o problema?

    Resposta: Provavelmente algum dos shell scripts necessários não está configurado com permissões de execução. Corrija as permissões dos ficheiros .sh por forma a terem permissões de execução para o seu utilizador.
    chmod +x *.sh


  3. Pergunta: Ao tentar aceder ao jUDDI+Tomcat, obtenho o erro: ... ServletException ... ConfigurationException ... URISyntaxException: Illegal character in path at index
    Qual o problema?

    Resposta: Provavelmente o caminho (path) para a pasta de instalação do jUDDI contém espaços ou caracteres acentuados.
    Instalar numa path sem espaços nem caracteres acentuados, por exemplo, em c:\temp\


  4. Pergunta: Ao tentar ligar-me ao UDDI, recebo a seguinte mensagem de erro: org.apache.commons.configuration.ConfigurationException: Cannot locate configuration source META-INF/uddi.xml
    Qual o problema?

    Resposta: O ficheiro uddi.xml serve para definir vários parâmetros que são necessários para a ligação ao UDDI registry (e.g. endereços do registry). O caminho do ficheiro uddi.xml é indicado nas propriedades da ligação ao UDDI registry, como se pode perceber no exemplo dado no tutorial de UDDI. Este erro denota que o pathname indicado para o ficheiro está errado. No caso de um web service, este ficheiro deve ser colocado na directoria WEB-INF/classes dentro do .war. No caso de uma aplicação consola, é necessário definir um pathname que seja correcto.


  5. Pergunta: Como posso limpar a base de dados do jUDDI através da linha de comandos?

    Resposta: Parar jUDDI/Tomcat (executar shutdown.bat / shutdown.sh caso não esteja).
    Apagar a directoria bin/target/juddi-derby-test-db.


  6. Pergunta: Como resolver o seguinte erro do UDDI?

    WSDLException (at /definitions/import[1]/definitions/import/definitions/types/xsd:schema/xsd:schema):
    faultCode=PARSER_ERROR: Problem parsing 'jar:file:/.../uddi-ws-3.1.3.jar!/www.w3.org/TR/xmldsig-core/xmldsig-core-schema.xsd'.:
    java.net.UnknownHostException: www.w3.org
    

    Resposta: O jUDDI gera os seus próprios Web Services a partir de diversos WSDL e um deles refere um schema no domínio www.w3.org.
    Isto significa que o jUDDI não funciona correctamente se a máquina não estiver ligada à internet.


  7. Pergunta: O que significam as mensagens da biblioteca SLF4J?

    Resposta: As linhas seguintes indicam que a biblioteca de logging SL4J não está incluída no classpath e que por isso as mensagens vão ser ignoradas.

        SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
        SLF4J: Defaulting to no-operation (NOP) logger implementation
        SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
    
    Estas linhas podem ser ignoradas, a não ser que se pretenda mesmo usar esta biblioteca. Nesse caso, consultar a página da biblioteca.


  8. Pergunta: Ainda tenhos erros no jUDDI ou wsimport que não são descritos noutras perguntas.
    Exemplo 1 : O projecto encontra-se localizado num caminho a começar por "C:\program files"

    directory not found: C:\program
    
    Exemplo 2 : O repositório local do maven encontra-se em "C:\users\André"
    Exception in thread "main" java.lang.ClassCastException: java.lang.AssertionError cannot be cast to java.lang.Exception
            at org.jvnet.jax_ws_commons.jaxws.Invoker.main(Invoker.java:87)
    
    Qual é o problema?

    Resposta: JUDDI e wsimport não funcionam bem com espaços e/ou caracteres acentuados na path de instalação (em Windows).
    Por exemplo, usar as seguintes directorias poderá dar problemas:

    C:\program files
    C:\users\André
    
    Sugestão:
    C:\java\
    C:\dev\
    


Dúvidas SOAP Handlers

  1. Pergunta: Como detectar se um SOAP Handler está a processar uma mensagem que está a entrar ou a sair?

    Resposta:

        /**
         *  This method checks if the SOAP message in context
         *  is going out of Web Service (outbound - true) or in (inbound - false).
         */
        public static boolean isOutboundMessage(SOAPMessageContext smc) {
            Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
            return outboundProperty.booleanValue();
        }
    


  2. Pergunta: Porque é que mesmo depois de substituir a mensagem SOAP por outra nova, esta última não é utilizada?

    Resposta: Internamente a biblioteca de Web Services guarda a referência para o objecto SOAPMessage original. Se se substituir a original por uma nova mensagem, não é lançada nenhuma excepção, mas a nova mensagem é ignorada e é usada a original (ou seja, aquela que continua a ser referenciada pelo Web Service). A forma de resolver este problema é manter a mensagem original mas substituir-lhe o conteúdo pelo da nova mensagem. Assim a referência interna da biblioteca de Web Services continua a ser válida.

    MessageFactory factory = MessageFactory.newInstance();
    SOAPMessage newMessage = factory.createMessage(oldMessage.getMimeHeaders(), inputByteArray);
    oldMessage.getSOAPPart().setContent(newMessage.getSOAPPart().getContent());
    


  3. Pergunta: É possível chamar uma operação de um Web Service remoto de dentro do método de um SOAPHandler?

    Resposta: Sim. Basta seguir a mesma abordagem usada para qualquer cliente de web service.


  4. Pergunta: A que se deve o erro Caused by: com.sun.xml.ws.util.UtilException: Could not find handler chain file ...Service_handler.xml for class ... ?

    Resposta: O ficheiro de configuração ...Service_handler.xml é gerado pelo wsimport juntamente com os stubs de invocação.
    Devido a um bug este ficheiro é por vezes apagado.

    A forma de contornar o erro é fazer uma compilação limpa: mvn clean compile
    ou forçar a inclusão do ficheiro de configuração através da seguinte definição no pom.xml do programa cliente:

        <build>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <filtering>true</filtering>
                </resource>
                <resource>
                    <directory>src/jaxws</directory>
                    <filtering>true</filtering>
                </resource>
            </resources>
    

    Para confirmar que o ficheiro faz parte do código, pode-se consultar a pasta target/classes


  5. Pergunta: Como pode um handler receber parâmetros de configuração? [atualizada]

    Resposta: Os handlers podem receber parâmetros via contexto (ver exemplo handler_relay), ou via variável de ambiente definida na VM, ou via ficheiro de propriedades (ver exemplo java-app-config).

    Caso se pretenda fazer uma configuração para todos os handlers da mesma classe numa dada VM, pode optar por uma variável public static na classe do Handler que é preenchida durante o arranque do programa.
    Na prática é uma variável global.


  6. Pergunta: Qual é a diferença na configuração de handlers no cliente e no servidor?

    Resposta: Ver esta client-ws-handlers-tutorial com ilustrações.



© Docentes de Sistemas Distribuídos, Dep. Eng. Informática, Instituto Superior Técnico, Universidade de Lisboa