pristupnatocka-tutorial-v2 / java / pristupnatocka-tutorial-java / README.md
README.md
Raw

pristupnatocka.hr Java tutorial

Uvod

Cilj ovog projekta je prikazati načina na koji se može implementirati komunikacija sa pristupnom točkom. Sam projekt sadrži već gotovu implementaciju jednog scenarija u obliku sekvencijalnih JUnit 5 testova. Testni scenariji se mogu vidjeti u klasi PristupnaTockaTest.

Tehnički preduvjeti

Koraci potrebni za implementaciju testnog scenarija

1. Kreiranje Apache Maven projekta

Projekt se može kreirati na više načina, koristeći IDE, terminal ili ručno. Za naš projekt je bitno sljedeće:

  • Naziv projekta: pti-hello-world
  • Java package: hr.pti.hw
  • Java klasa koja će se izvršiti prilikom pokretanja programa: App.java
  • Maven konfiguracija projekta: pom.xml

Inicijalna struktura projekta

pti-hello-world 
├── pom.xml
└── src
    └── main
        └── java
            └── hr
                └── pti
                    └── hw
                        └── App.java

App.java

package hr.pti.hw;

public class App {

  public static void main(String[] args) {}
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project
  xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>hr.pti.hw</groupId>
  <artifactId>pti-hello-world</artifactId>
  <version>1.0.0</version>
  <packaging>jar</packaging>
  <properties>
    <exec.mainClass>hr.pti.hw.App</exec.mainClass>
  </properties>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.10.1</version>
        <configuration>
          <source>11</source>
          <target>11</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Za provjeru da je projekt u redu, probajte izvršiti sljedeću naredbu u terminalu:

# Za ovu naredbu je preduvjet da je Apache Maven dostupan u terminalu
# Alternativa je da jednostavno probate pokrenuti App.java klasu iz IDE-a
mvn exec:java

2. Kreiranje truststore-a

Za komunikaciju sa pristupnom točkom potrebno je uspostaviti tzv. SSL handshake. Za to nam je potreban trusted certifikat kojeg možemo skinuti direktno sa pristupne točke putem npr. browser-a (skinuti certifikati imaju ekstenziju .cer, .pem isl.). Taj certifikat je potom potrebno pohraniti u tzv. Java truststore koji se koristi prilikom uspostave HTTP konekcije sa pristupnom točkom. Ukoliko želite preskočiti ovaj korak, projekt sadrži već pripremljen truststore sa svim certifikatima koje je moguce skinuti sa pristupne točke. Password za taj truststore je changeit. Sve certifikate (za komunikaciju je potreban samo jedan, onaj sa CN=*.pristupnatocka.hr) koje možete skinuti sa testne pristupne točke također možete pronaći u direktoriju cert.

Kreirani truststore potrebno je smjesiti u direktorij src/main/resources

pti-hello-world
├── pom.xml
└── src
    └── main
        ├── java
        │   └── hr
        │       └── pti
        │           └── hw
        │               └── App.java
        └── resources
            └── truststore.jks

3. WSDL (Web Services Description Language)

Tehnički gledano ovaj korak nije potreban da bi se razmjenjivale SOAP poruke ali uvelike olakšava posao konverzije XML poruka u Java objekte što olakšava korištenje i slanje samih poruka u kodu. XML primjere poruka koje u konačnici nastaju iz generiranih Java klasa možete vidjeti u direktoriju soap-messages.

WSDL testne pristupne točke dostupan je na wsdl url. WSDL je potrebno pohraniti kao datoteku s nazivom npr. backend.wsdl u direktorij src/main/resources. Projekt sadrži već pripremljenu backend.wsdl datoteku.

pti-hello-world
├── pom.xml
└── src
    └── main
        ├── java
        │   └── hr
        │       └── pti
        │           └── hw
        │               └── App.java
        └── resources
            ├── backend.wsdl
            └── truststore.jks

4. Generiranje Java klasa temeljem backend.wsdl datoteke

Postoji nekoliko načina na koji se mogu generirati Java klase koje će nam služiti za komunikaicju sa pristupnom točkom. Mi ćemo u našem primjeru koristiti Apache Maven plugin cxf-codegen-plugin.

  • Ažurirajte pom.xml datoteku na sljedeći način:

    <?xml version="1.0" encoding="UTF-8"?>
    <project
      xmlns="http://maven.apache.org/POM/4.0.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>hr.pti.hw</groupId>
      <artifactId>pti-hello-world</artifactId>
      <version>1.0.0</version>
      <packaging>jar</packaging>
      <properties>
        <exec.mainClass>hr.pti.hw.App</exec.mainClass>
        <cxf.version>4.0.0</cxf.version>
      </properties>
      <dependencies>
        <dependency>
          <groupId>org.apache.cxf</groupId>
          <artifactId>cxf-rt-frontend-jaxws</artifactId>
          <version>${cxf.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.cxf</groupId>
          <artifactId>cxf-rt-transports-http</artifactId>
          <version>${cxf.version}</version>
        </dependency>
        <dependency>
          <groupId>org.junit.jupiter</groupId>
          <artifactId>junit-jupiter-api</artifactId>
          <version>5.9.0</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>org.junit.jupiter</groupId>
          <artifactId>junit-jupiter-params</artifactId>
          <version>5.9.0</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.10.1</version>
            <configuration>
              <source>11</source>
              <target>11</target>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    
  • Za generiranje Java klasa pokrenite Maven naredbu

    mvn clean compile
    

    Ukoliko je sve dobro prošlo, u direktoriju src/main/java bi se trebali pojaviti novi direktoriji backend i org unutar kojih se nalaze generirane Java klase.

5. Konfiguriranje klijenta za komunikaciju sa pristupnom točkom

U direktoriju src/main/java/hr/pti/hw krerirajte Java klasu PTClient.java. Ova klasa je samo bazični primjer kako bi neka konfiguracija klijenta mogla izgledati. Klase koje su koriste u kodu (počinju sa backend.ecodex.org) su nastale generiranje koda temeljem backend.wsdl datoteke.

package hr.pti.hw;

import backend.ecodex.org._1_1.BackendInterface;
import backend.ecodex.org._1_1.BackendService11;
import jakarta.xml.ws.BindingProvider;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import javax.net.ssl.TrustManagerFactory;

import jakarta.xml.ws.soap.SOAPBinding;
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.http.HTTPConduit;

public final class PTClient {

  public static BackendInterface buildClient(
      String url,
      String user,
      String userPassword,
      InputStream truststore,
      String truststorePassword)
      throws IOException, GeneralSecurityException {
    JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();
    proxyFactory.setServiceClass(BackendService11.class);

    BackendInterface backendInterface = proxyFactory.create(BackendInterface.class);

    Client client = ClientProxy.getClient(backendInterface);
    HTTPConduit httpConduit = (HTTPConduit) client.getConduit();

    TLSClientParameters tlsCP = new TLSClientParameters();
    tlsCP.setDisableCNCheck(true);

    // Koristimo truststore koji smo kreirali u koraku 2.
    // Učitaj store
    KeyStore keyStore = KeyStore.getInstance("JKS");
    keyStore.load(truststore, truststorePassword.toCharArray());

    // Iz store povuci trusted certifikate i koristi ih za TLS
    TrustManagerFactory tmf =
        TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(keyStore);
    tlsCP.setTrustManagers(tmf.getTrustManagers());

    httpConduit.setTlsClientParameters(tlsCP);

    BindingProvider bindingProvider = (BindingProvider) backendInterface;
    bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
    bindingProvider.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, user);
    bindingProvider.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, userPassword);

    SOAPBinding soapBinding = (SOAPBinding) bindingProvider.getBinding();
    soapBinding.setMTOMEnabled(true);

    return backendInterface;
  }
}

6. Kako pozvati metodu pristupne točke?

U našem slučaju, pozvat ćemo metodu getStatus koja vraća status za zatraženi messageID.

Ažurirajte App.java klasu na sljedeći način:

package hr.pti.hw;

import backend.ecodex.org._1_1.BackendInterface;
import backend.ecodex.org._1_1.MessageStatus;
import backend.ecodex.org._1_1.StatusFault;
import backend.ecodex.org._1_1.StatusRequest;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.UUID;

public class App {

  public static void main(String[] args) throws IOException, GeneralSecurityException, StatusFault {
    // Koristimo PTClient.java klasu iz prethodnog koraka
    BackendInterface client =
        PTClient.buildClient(
            // Testna pristupna točka tenanta jpt99901
            // Na svim mjestima zamijenite jpt99901 sa svojim identifikatorom
            "https://jpt99901.test.pristupnatocka.hr/ws",
            // Dodijeljeni servisni korisnik
            "jpt99901",
            // Lozinka dodijeljenog servisnog korisnika
            "Password123456789!",
            App.class.getResourceAsStream("/truststore.jks"),
            "changeit");

    // Kreiraj poruku
    StatusRequest statusRequest = new StatusRequest();
    statusRequest.setMessageID(UUID.randomUUID().toString());

    // Zatraži status poruke od pristupne točke
    MessageStatus status = client.getStatus(statusRequest);

    // S obzirom na to da smo zatražili status poruke sa messageID koji ne postoji,
    // pristupna točka bi trebala vratiti odgovor NOT_FOUND
    System.out.println(status);
  }
}

Program pokrenite iz IDE-a ili koristeći Apache Maven naredbu:

mvn exec:java

Napomena

Primjere kreiranja i slanja ostalih vrsta poruka možete vidjeti u PristupnaTockaTest.java klasi.

Pokretanje testnog scenarija

Testni scenarij prikazuje slanje poruke iz jedne pristupne točke na drugu. Samo slanje poruke je konfigurabilno putem sistemskih varijabli.

Environment varijable za testni scenarij

# URL pristupne točke
pt.url=

# ID inicijatora na pristupnoj točki
pt.from=

# ID primatelja na pristupnoj točki
pt.to=

# Lozinka korisnika koji šalje poruku
pt.password=

Primjer

# Primjer pokretanja testnog scenarija se pokreće sljedećom Apache Maven naredbom
# Zamijenite jpt99901 sa svojim identifikatorom i upotrijebite dodijeljenu lozinku
mvn \
  -Dpt.url="https://jpt99901.test.pristupnatocka.hr/ws" \
  -Dpt.from=jpt99901 \
  -Dpt.to=jpt99901 \
  -Dpt.password=Password123456789! \
  compile test

Poruka koja se šalje je asice-sample.asice i možete ju otvorite sa nekim alatom koji zna raditi sa .zip arhivama kao npr. 7-zip isl.

Pristupna točka i mrežna adresa

Da bi uspješno testirali slanje poruke iz vlastitog sustava možete koristiti dostupnu testnu pristupnu točku koja sadrži predefiniranog tenanta kojem možete poslati poruku.

URL - mrežna adresa PartyId
https://jpt99901.test.pristupnatocka.hr/ws jpt99901

Važno

PartyId je obavezni dio mrežne adrese pristupne točke. Iz svake mrežne adrese može se dobiti i pripadni identifikator (PartyId), tj. vlasnik mrežne adrese.