April 5, 2019

Getting Started with JSF 2.3 and Bootstrap 4

Introduction

The most popular CSS framework today is Bootstrap.

We are now going to add Bootstrap to my previous getting started JSF 2.3 (Java EE 8).

Starting Files

  • pom.xml
  • src/main/java/se/magnuskkarlsson/jsf23/boundary/PersonBacking.java
  • src/main/webapp/welcome-bootstrap.xhtml (Copy of welcome.xhtml so far)
  • src/main/webapp/WEB-INF/web.xml
  • src/main/webapp/WEB-INF/beans.xml

Download Bootstrap

Open https://getbootstrap.com/ and click Download and then download "Compiled CSS and JS".

Unzip bootstrap-4.3.1-dist.zip to src/main/webapp/ so you have:

  • src/main/webapp/bootstrap-4.3.1-dist/css/
  • src/main/webapp/bootstrap-4.3.1-dist/js/

Bootstrap Template

Then go back to https://getbootstrap.com/ and click Get Started, there you will see a Bootstrap getting started template. Lets add that to our welcome-bootstrap.xhtml.

NOTE Since we are using xhtml, we need to close elements and have a well formatted file.


<!DOCTYPE html>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:f="http://xmlns.jcp.org/jsf/core">

    <h:head>
        <!-- Required meta tags -->
        <meta charset="utf-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>

        <!-- Bootstrap CSS -->
        <link rel="stylesheet" href="bootstrap-4.3.1-dist/css/bootstrap.min.css"/>

        <title>Hello JSF 2.3 and Bootstrap 4</title>
    </h:head>
    <h:body>
        <h:form>
            <h:outputLabel for="name" value="Who do you want to greet?"/>
            <h:inputText id="name" value="#{personBacking.name}" />
            <h:commandButton value="Submit" action="#{personBacking.submit()}">
                <f:ajax execute="@form" render=":message"/>
            </h:commandButton>
        </h:form>
        <br/>
        <h:outputText id="message" value="#{personBacking.message}"/>  

        <!-- Optional JavaScript -->
        <!-- jQuery first, then Popper.js, then Bootstrap JS -->
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
        <script src="bootstrap-4.3.1-dist/js/bootstrap.min.js"></script>
    </h:body>
</html>

Lets Use Bootstrap 4

Now lets use some bootstrap CSS classes.

Form: we need to add class="form-group" for each input for a vertical layout and for each input field add class="form-control".

Button: for our submit button we add class="btn btn-primary".

Overall layout: to add some space to the side lets add main container class.

Card: Which was panel in Bootstrap 3, we add class="card", class="card-body" and class="card-title".


<!DOCTYPE html>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:f="http://xmlns.jcp.org/jsf/core">

    <h:head>
        <!-- Required meta tags -->
        <meta charset="utf-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>

        <!-- Bootstrap CSS -->
        <link rel="stylesheet" href="bootstrap-4.3.1-dist/css/bootstrap.min.css"/>

        <title>Hello JSF 2.3 and Bootstrap 4</title>
    </h:head>
    <h:body>
        <div class="container">
            <div class="card">
                <div class="card-body">
                    <h5 class="card-title">
                        <h:outputText id="message" value="#{personBacking.message}"/>  
                    </h5>
                    <h:form>
                        <div class="form-group">
                            <h:outputLabel for="name" value="Who do you want to greet?"/>
                            <h:inputText id="name" value="#{personBacking.name}" class="form-control" />
                        </div>
                        <h:commandButton value="Submit" action="#{personBacking.submit()}" class="btn btn-primary">
                            <f:ajax execute="@form" render=":message"/>
                        </h:commandButton>
                    </h:form>
                </div>
            </div>
        </div>

        <!-- Optional JavaScript -->
        <!-- jQuery first, then Popper.js, then Bootstrap JS -->
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
        <script src="bootstrap-4.3.1-dist/js/bootstrap.min.js"></script>
    </h:body>
</html>

Test

Lets build, deploy and test it and then open for (JBoss EAP 7.2) http://localhost:8080/example-jsf23/welcome-bootstrap.xhtml.

Getting Started with JSF 2.3 (Java EE 8)

Introduction

JSF 2.3 comes with Java EE 8.

Maven

Add Java EE 8 dependency and Java 11 (latest Java LTS version).


<?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>se.magnuskkarlsson</groupId>
    <artifactId>example-jsf23</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.build.outputEncoding>UTF-8</project.build.outputEncoding>
        <maven.compiler.release>11</maven.compiler.release>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>8.0</version>
            <scope>provided</scope>
        </dependency>
 
        <!-- Test Support -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
 
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.10.19</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <build>
        <finalName>${project.artifactId}</finalName>
    </build>
</project> 

Facelet/JSF Page

In JSF you use Facelet, which you are xhtml files. Earlier we used HTML 4.01, but now we use HTML 5.

<h:head> and <h:body> are mandatory to make JSF work.

Lets write a simple Facelet src/main/webapp/welcome.xhtml.


<!DOCTYPE html>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:f="http://xmlns.jcp.org/jsf/core">

    <h:head>
        <title>Welcome JSF 2.3</title>
    </h:head>
    <h:body>
        <h:form>
            <h:outputLabel for="name" value="Who do you want to greet?"/>
            <h:inputText id="name" value="#{personBacking.name}" />
            <h:commandButton value="Submit" action="#{personBacking.submit()}">
                <f:ajax execute="@form" render=":message"/>
            </h:commandButton>
        </h:form>
        <br/>
        <h:outputText id="message" value="#{personBacking.message}"/>  
    </h:body>
</html>

web.xml

web.xml is no longer necessary, but to hide the source code of your xhtml files we explicitly set Facelet servlet to react on xhtml file extension.

src/main/webapp/WEB-INF/web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee webapp_4_0.xsd"
         version="4.0">
    
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>welcome.xhtml</welcome-file>
    </welcome-file-list>
</web-app>

beans.xml

To make CDI work we need to add an empty src/main/webapp/WEB-INF/beans.xml.


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
       bean-discovery-mode="all"
       version="2.0">

</beans>

Backing Bean

In Java EE 8 the JSF Backing Bean or Managed Bean are deprecated, so now we use standard CDI.


package se.magnuskkarlsson.jsf23.boundary;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

@Named
@RequestScoped
public class PersonBacking {

    private String name;
    private String message;

    // ----------------------- Logic Methods -----------------------
    
    public void submit() {
        message = "Greeting " + name;
    }

    // ----------------------- Helper Methods -----------------------
    
    // ----------------------- Get and Set Methods -----------------------
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMessage() {
        return message;
    }

}

Test

Build and deploy to an Java EE 8 container such as JBoss EAP 7.2, then open http://localhost:8080/example-jsf23/welcome.xhtml.

March 28, 2019

Entity Control Boundary (ECB) Pattern

Introduction

The Entity Control Boundary (ECB) pattern is and old pattern that was published by Ivar Jacobson (Ericsson Co.) in 80's. It is has things in common with the Model View Controller (MVC) Pattern that was published by Trygve Reenskaug (XEROX Co.) in 70's. The MVC pattern is mainly used in User Interface, where the ECB is a general pattern to structure your backend.

Entity Control Boundary (ECB) Pattern

The ECB Pattern is built up by

  • Boundary - the API for your component. Today typically a REST API, but could be Web Service, JMS, etc. It is the external interface for your component.
  • Control - encapsulate the Logic for your component.
  • Entity - -the Model
https://stackoverflow.com/questions/683825/in-uml-class-diagrams-what-are-boundary-classes-control-classes-and-entity-cl


Example of ECB


https://creately.com/diagram/example/hav994lu1/Boundary%20Control%20Entity


Comparison between ECB and MVC Pattern


https://stackoverflow.com/questions/26910974/model-view-controller-vs-boundary-control-entity


March 26, 2019

Syslog Handler in JBoss EAP 6 and 7

Introduction

JBoss EAP 6 and 7 has a two different syslog handler:

  • syslog-handler
  • custom-handler org.jboss.logmanager.handlers.SyslogHandler

syslog-handler

The default syslog-handler only supports UDP.


$ ./jboss-cli.sh -c

/subsystem=logging/syslog-handler=SYSLOG_HANDLER:add()

/subsystem=logging/syslog-handler=SYSLOG_HANDLER:read-resource-description


attribute description expressions-allowed default allowed
level The log level specifying which message levels will be logged by this logger. Message levels lower than this value will be discarded. true ALL  
enabled If set to true the handler is enabled and functioning as normal, if set to false the handler is ignored when processing log messages. true true  
server-address The address of the syslog server. true localhost  
port The port the syslog server is listening on. true 514  
facility Facility as defined by RFC-5424 (http://tools.ietf.org/html/rfc5424)and RFC-3164 (http://tools.ietf.org/html/rfc3164). true user-level kernel
user-level
mail-system
system-daemons
security
syslogd
line-printer
network-news
uucp
clock-daemon
security2
ftp-daemon
ntp
log-audit
log-alert
clock-daemon2
local-use-0
local-use-1
local-use-2
local-use-3
local-use-4
local-use-5
local-use-6
local-use-7
hostname The name of the host the messages are being sent from. For example the name of the host the application server is running on. true    
app-name The app name used when formatting the message in RFC5424 format. By default the app name is \"java\". true java  
syslog-format Formats the log message according to the RFC specification. true RFC5424 RFC5424
RFC3164


custom-handler

custom-handler org.jboss.logmanager.handlers.SyslogHandler is located in jboss-logmanager-.jar and supports UDP, TCP and TLS.

  • jboss-eap-6.4.0/modules/system/layers/base/org/jboss/logmanager/main/jboss-logmanager-1.5.4.Final-redhat-1.jar
  • jboss-eap-7.2.0/modules/system/layers/base/org/jboss/logmanager/main/jboss-logmanager-2.1.5.Final-redhat-00001.jar
Property Description Type Default
serverHostname The address of the syslog server String localhost
port The port of the syslog server int 514
facility The facility used to calculate the priority of the log message CLOCK_DAEMON
CLOCK_DAEMON2
FTP_DAEMON
KERNEL
LINE_PRINTER
LOCAL_USE_0
LOCAL_USE_1
LOCAL_USE_2
LOCAL_USE_3
LOCAL_USE_4
LOCAL_USE_5
LOCAL_USE_6
LOCAL_USE_7
LOG_ALERT
LOG_AUDIT
MAIL_SYSTEM
NETWORK_NEWS
NTP
SECURITY
SECURITY2
SYSLOGD
SYSTEM_DAEMONS
USER_LEVEL
UUCP
USER_LEVEL
appName The name of the application that is logging String java
hostname The name of the host the messages are being sent from. String null
syslogType The type of the syslog used to format the message RFC5424
RFC3164
RFC5424
protocol The protocol to send the message over UDP
TCP
SSL_TCP
UDP
delimiter The delimiter to use at the end of the message if useDelimiter is set to true String For UDP null.
For TCP or SSL_TCP '\n'.
useDelimiter Whether or not the message should be appended with a delimiter boolean For UDP false.
For TCP or SSL_TCP true.
useCountingFraming Prefixes the size of the message, mainly used for TCP or SSL_TCP, connections to the message being sent to the syslog server. See http://tools.ietf.org/html/rfc6587 for more details on framing types. boolean false
truncate Whether or not a message, including the header, should truncate the message if the length in bytes is greater than the maximum length. If set to false messages will be split and sent with the same header values. boolean true
maxLength The maximum length a log message, including the header, is allowed to be. int For RFC3164 1024 (1k).
For RFC5424 2048 (2k)
.


Example


<custom-handler name="SYSLOG" class="org.jboss.logmanager.handlers.SyslogHandler" module="org.jboss.logmanager">
    <encoding value="UTF-8"/>
    <formatter>
        <pattern-formatter pattern="%s%E%n"/>
    </formatter>
    <properties>
        <property name="serverHostname" value="192.168.122.43"/>
        <property name="port" value="514"/>
        <property name="facility" value="LOCAL_USE_6"/>
        <property name="appName" value="JBossEAP"/>
        <property name="hostname" value="localhost.localdomain"/>
        <property name="syslogType" value="RFC3164"/>
        <property name="protocol" value="TCP"/>
        <property name="truncate" value="false"/>
        <property name="maxLength" value="4096"/>
    </properties>
</custom-handler>

February 18, 2019

RPM Installation of WildFly 15 on CentOS 7

Prerequisite

CentOS 7. I use minimal installation. I also need wget to download harbottle rpm repo (https://pkgs.org/download/wildfly), from which I will need to install WilfFly from. The harbottle repo is a Fedora Project repo. And Fedora is supported by Red Hat.


# yum install wget -y

Install HarBottle RPM Repo


# wget https://harbottle.gitlab.io/harbottle-main/7/x86_64/00703701-harbottle-main-release/harbottle-main-release-7-5.el7.noarch.rpm
# rpm -Uvh harbottle-main-release*rpm

Check the HarBottle RPM.


# rpm -ql harbottle-main-release
/etc/yum.repos.d/harbottle-main.repo
/usr/share/doc/harbottle-main-release-7
/usr/share/doc/harbottle-main-release-7/GPL
# rpm -q --scripts harbottle-main-release
# cat /etc/yum.repos.d/harbottle-main.repo
[harbottle-main]
name=Copr repo for main owned by harbottle
baseurl=https://copr-be.cloud.fedoraproject.org/results/harbottle/main/epel-7-$basearch/
type=rpm-md
skip_if_unavailable=True
gpgcheck=1
gpgkey=https://copr-be.cloud.fedoraproject.org/results/harbottle/main/pubkey.gpg
repo_gpgcheck=0
enabled=1
enabled_metadata=1

gpgcheck=value

Use the gpgcheck option to specify if yum should perform a GPG signature check on packages. Replace value with:

0 — Disable GPG signature-checking on packages in all repositories, including local package installation.

1 (default) — Enable checking of GPG signature on all packages in all repositories, including local package installation. With gpgcheck enabled, all packages' signatures are checked."

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system_administrators_guide/sec-configuring_yum_and_yum_repositories

repo_gpgcheck=0

https://github.com/ComplianceAsCode/content/issues/1596

Check rpm repo server certificate.


# openssl s_client -connect copr-be.cloud.fedoraproject.org:443 -showcerts
...
---
Server certificate
subject=/C=US/ST=North Carolina/L=Raleigh/O=Red Hat, Inc./OU=Fedora Infrastructure/CN=copr.fedorainfracloud.org
issuer=/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
---
...

Install WilfFly RPM

Install WildFly Current (Now 15.0.1). Dubble check it is the current WildFly version at http://wildfly.org/downloads/.


# yum install wildfly
...
 java-1.8.0-openjdk
 java-1.8.0-openjdk-devel
 java-1.8.0-openjdk-headless
...
Retrieving key from https://copr-be.cloud.fedoraproject.org/results/harbottle/main/pubkey.gpg
Importing GPG key 0xE148E740:
 Userid     : "harbottle_main (None) <harbottle#main@copr.fedorahosted.org>"
 Fingerprint: f1df c563 31a9 d77e a8cc ae17 df9b 4194 e148 e740
 From       : https://copr-be.cloud.fedoraproject.org/results/harbottle/main/pubkey.gpg
...

Tour of the WildFly RPM

Start and Auto Start WildFly.


# systemctl start wildfly
# systemctl enable wildfly

Server log.


# less /usr/share/wildfly/standalone/log/server.log

JBoss Home Standalone


# ll /usr/share/wildfly/standalone/
total 0
lrwxrwxrwx. 1 root root 23 Feb 18 13:51 configuration -> /etc/wildfly/standalone
lrwxrwxrwx. 1 root root 32 Feb 18 13:51 data -> /var/lib/wildfly/standalone/data
lrwxrwxrwx. 1 root root 39 Feb 18 13:51 deployments -> /var/lib/wildfly/standalone/deployments
lrwxrwxrwx. 1 root root 31 Feb 18 13:51 lib -> /var/lib/wildfly/standalone/lib
lrwxrwxrwx. 1 root root 27 Feb 18 13:51 log -> /var/log/wildfly/standalone
lrwxrwxrwx. 1 root root 33 Feb 18 13:51 tmp -> /var/cache/wildfly/standalone/tmp

JBoss System Unit Global Configuration.


# ll /etc/wildfly/
total 12
drwxrwxr-x. 2 root wildfly   53 Feb 18 13:51 appclient
drwxrwxr-x. 2 root wildfly  283 Feb 18 13:51 domain
-rw-r--r--. 1 root root    3035 Jan  5 20:10 jboss-cli.xml
drwxrwxr-x. 3 root wildfly 4096 Feb 18 14:03 standalone
-rw-r--r--. 1 root root     170 Jan 14 17:09 wildfly.conf

# cat /etc/wildfly/wildfly.conf 
# The configuration you want to run
#
WILDFLY_CONFIG=standalone.xml

# The mode you want to run
WILDFLY_MODE=standalone

# The address to bind to
#
WILDFLY_BIND=0.0.0.0

Test It


# systemctl stop firewalld
# ip addr show
...
    inet 192.168.122.43/24 brd 192.168.122.255 scope global noprefixroute dynamic eth0
...

Now open a remote browser and enter http://192.168.122.43:8080/.

November 20, 2018

Setting Global HTTP Session Timeout in JBoss EAP 6 and 7

JBoss EAP 6.x

Edit standalone.xml.


<subsystem xmlns="urn:jboss:domain:web:2.2" default-virtual-server="default-host" native="false" default-session-timeout="15">
...
</subsystem>

JBoss EAP 7.x

Edit standalone.xml.


<subsystem xmlns="urn:jboss:domain:undertow:4.0">
...
    <servlet-container name="default" default-session-timeout="15">
...
    </servlet-container>
...
</subsystem>

Note

You can set this in WEB-INF/web.xml also, but this is better to set globally.

Set HttpOnly and secure for Cookies in JBoss EAP 6 and 7

What is Cookie HttpOnly and secure?

Example

Set-Cookie: a=b; HttpOnly; SameSite=strict; secure

HttpOnly = No JavaScript

SameSite = no cross-origin cookie sharing

secure = SSL only

SameSite is not yet supported in all browser, see https://caniuse.com/#feat=same-site-cookie-attribute

JBoss EAP 6.x

Not supported to set globally. Best effort is deploy Servlet 3.0 web-fragment.xml and deploy overlay which is messy.

Next best in local application WEB-INF/web.xml.


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
...
    <session-config>
        <!-- Session timeout after X MINUTES after no user interaction. -->
        <session-timeout>15</session-timeout>
        <cookie-config>
            <http-only>true</http-only>
            <secure>true</secure>
        </cookie-config>
        <tracking-mode>COOKIE</tracking-mode>
    </session-config>
</web-app>

JBoss EAP 7.x

Edit standalone.xml


<subsystem xmlns="urn:jboss:domain:undertow:4.0">
...
    <servlet-container name="default">
...
        <session-cookie http-only="true" secure="true" />
    </servlet-container>
...
</subsystem>