Skip to content

devon4j deployment

Philip Schimmelpfennig edited this page Oct 15, 2019 · 20 revisions

Deployment of devon4j applications

As we already mentioned when introducing the devon4j projects, the apps created with the devon4j archetype are going to provide, apart from the core project and api project, a server project that will configure the packaging of the app.

In our Jump the Queue app we can verify that we have this server project available

jumpthequeue server structure

So, using Maven, we are going to be able to easily package our app in a .war file to be deployed in an application server like Tomcat (the default server provided in devonfw).

The server project

The server project provided in devon4j applications is an almost empty Maven project. It only has a pom.xml file that is used to configure the packaging of the core project. Taking a closer look to this pom.xml file we can realize that it only presents a single dependency to the core project.

...

<dependencies>
<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>jumpthequeue-core</artifactId>
    <version>${project.version}</version>
</dependency>
</dependencies>
...

And then it includes the spring-boot-maven-plugin that allows us to package the project in a jar or war archives and run the application "in-place".

...

<plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    ...

Disabling security tests

First, since this is a basic tutorial and there is no security/permissions,the files SecurityRestServiceImplTest and the PermissionCheckTest need to be modified leaving one test of each that will return true and the rest in a commentary. First, in the core jtqj-core inside src/test/java/…​/general/common/service/impl/rest/SecurityRestServiceImplTest:

....
public class SecurityRestServiceImplTest extends RestServiceTest {
  ....
  @Test
  public void testLogin() {

	assertThat(true);
   /**String login = "waiter";
    String password = "waiter";

    ResponseEntity<String> postResponse = login(login, password);
    LOG.debug("Body: " + postResponse.getBody());
    assertThat(postResponse.getStatusCode()).isEqualTo(HttpStatus.OK);
    assertThat(postResponse.getHeaders().containsKey(HttpHeaders.SET_COOKIE)).isTrue();*/
  }
  ....
 /** @Test
  public void testGetCsrfToken() {

    String login = "waiter";
    String password = "waiter";
    SecurityRestService securityService = getServiceClientFactory().create(SecurityRestService.class,
        new ServiceClientConfigBuilder().host("localhost").authBasic().userLogin(login).userPassword(password)
            .buildMap());
    CsrfToken csrfToken = securityService.getCsrfToken(null, null);
    assertThat(csrfToken.getHeaderName()).isEqualTo("X-CSRF-TOKEN");
    assertThat(csrfToken.getParameterName()).isEqualTo("_csrf");
    assertThat(csrfToken.getToken()).isNotNull();
    LOG.debug("Csrf Token: {}", csrfToken.getToken());
  }*/
  ....
 /**@Test
  public void testGetCurrentUser() {
    String login = "waiter";
    String password = "waiter";
    SecurityRestService securityService = getServiceClientFactory().create(SecurityRestService.class,
        new ServiceClientConfigBuilder().host("localhost").authBasic().userLogin(login).userPassword(password)
            .buildMap());
    UserProfileTo userProfile = securityService.getCurrentUser();
    assertThat(userProfile.getLogin()).isEqualTo(login);
  }*/
  ....
  /**ResponseEntity<String> login(String userName, String tmpPassword) {

    String tmpUrl = "http://localhost:" + String.valueOf(this.port) + "/services/rest/login";

    HttpEntity<String> postRequest = new HttpEntity<>(
        "{\"j_username\": \"" + userName + "\", \"j_password\": \"" + tmpPassword + "\"}", new HttpHeaders());

    ResponseEntity<String> postResponse = new RestTemplate().exchange(tmpUrl, HttpMethod.POST, postRequest, String.class);
    return postResponse;
  }*/
  ....
}
And then inside `src/test/.../general/common/base/PermissionCheckTest`:
....
public class PermissionCheckTest extends ModuleTest {
  ....
  @Test
  public void permissionCheckAnnotationPresent() {

	assertThat(true);
    /**String packageName = "com.devonfw.application.jtqj";
    Filter<String> filter = new Filter<String>() {

      @Override
      public boolean accept(String value) {

        return value.contains(".logic.impl.usecase.Uc") && value.endsWith("Impl");
      }

    };
    ReflectionUtil ru = ReflectionUtilImpl.getInstance();
    Set<String> classNames = ru.findClassNames(packageName, true, filter);
    Set<Class<?>> classes = ru.loadClasses(classNames);
    SoftAssertions assertions = new SoftAssertions();
    for (Class<?> clazz : classes) {
      Method[] methods = clazz.getDeclaredMethods();
      for (Method method : methods) {
        Method parentMethod = ru.getParentMethod(method);
        if (parentMethod != null) {
          Class<?> declaringClass = parentMethod.getDeclaringClass();
          if (declaringClass.isInterface() && declaringClass.getSimpleName().startsWith("Uc")) {
            boolean hasAnnotation = false;
            if (method.getAnnotation(RolesAllowed.class) != null || method.getAnnotation(DenyAll.class) != null
                || method.getAnnotation(PermitAll.class) != null) {
              hasAnnotation = true;
            }
            assertions.assertThat(hasAnnotation)
                .as("Method " + method.getName() + " in Class " + clazz.getSimpleName() + " is missing access control")
                .isTrue();
          }
        }
      }
    }
    assertions.assertAll();*/
  }
  ....
}
....

This is going to allow our application to pass the tests and be able to build.

Running the app with Maven

Thanks to Spring Boot and the spring-boot-maven-plugin we can run our app using Maven. To do so just open a command line with access to Maven (in Devonfw we can do it using the console.bat). And:

1.- As is explained in devonfw documentation the application.properties used for packaging is /src/main/resources/application.properties. So we need to edit the app properties to access to the app. In /jtqj-core/src/main/resources/application.properties configure the properties:

server.port=8081
server.servlet.context-path=/jumpthequeue

2.- install the jtqj project in our local Maven repository

D:\Devon-dist\...\jtqj>mvn install

3.- Go to the jtqj/server project and execute the command mvn spring-boot:run

D:\Devon-dist\...\jtqj\server>mvn spring-boot:run

The app should be launched in the Spring Boot embedded Tomcat server. Wait a few seconds until you see a console message like

{"timestamp":"2019-01-30T14:13:10.164+00:00","message":"Tomcat started on port(s): 8081 (http) with context path '/jumpthequeue'","logger_name":"org.springframework.boot.web.embedded.tomcat.TomcatWebServer","thread_name":"main","level":"INFO","appname":"jtqj"}

Now we can try to access to the app resource (GET)http://localhost:8081/jumpthequeue/services/rest/visitormanagement/v1/visitor/1 we can verify that the app is running fine

jumpthequeue simpleget1

Packaging the app with Maven

In the same way, using Maven we can package our project in a .war file. As in the previous section, open a command line with access to Maven (in devonfw console.bat script) and execute the command mvn clean package in the project root directory

D:\Devon-dist\...\jtqj>mvn clean package

The packaging process (compilation, tests and .war file generation) should be launched. Once the process is finished you should see a result like

[INFO] Building war: C:\Devon-dist_3.0.0\jump-the-queue\java\jtqj\server\target\jtqj-server-v4.war
[INFO]
[INFO] --- spring-boot-maven-plugin:2.0.4.RELEASE:repackage (default) @ jtqj-server ---
[INFO] Attaching archive: C:\...\jump-the-queue\java\jtqj\server\target\jtqj-server-bootified.war, with classifier: bootified
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for jtqj v4:
[INFO]
[INFO] jtqj ............................................... SUCCESS [  2.582 s]
[INFO] jtqj-api ........................................... SUCCESS [  6.725 s]
[INFO] jtqj-core .......................................... SUCCESS [01:19 min]
[INFO] jtqj-server ........................................ SUCCESS [ 10.308 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

The packaging process has created a .war file that has been stored in the \java\jtqj\server\target directory.

Clone this wiki locally