Categories
Java

Generate Test Data

I need some test data to be displayed in my PrimeFaces Template App.

A good library to generate fake data is: Java Faker.

Add Java Faker to dependencies in Maven:

		<dependency>
			<groupId>com.github.javafaker</groupId>
			<artifactId>javafaker</artifactId>
			<version>1.0.2</version>
		</dependency>

For Example I want to have a Person with following fields:

	private String firstName;
	private String lastName;
	private Date dayOfBirth;
	private String phoneNumber;
	private String streetName;
	private String streetAddressNumber;
	private String zipCode;
	private String city;
	private String state;

A Person can be generated with fake data from Java Faker like this:

String firstName = faker.name().firstName();
String lastName = faker.name().lastName();
Date dayOfBirth = faker.date().birthday();
String phoneNumber = faker.phoneNumber().phoneNumber();
String streetName = faker.address().streetName();
String streetAddressNumber = faker.address().streetAddressNumber();
String zipCode = faker.address().zipCode();
String city = faker.address().city();
String state = faker.address().state();

Person person = new Person(firstName, lastName, dayOfBirth, phoneNumber, streetName, streetAddressNumber, zipCode, city, state);

Categories
Java

Test driven Json Analysis

To analyse an unknown Json API I setup a small project with Smallrye Rest Client to access the Json structure. I added JUnit for a test driven approach and Hamcrest for Matchers (like assertThat or is).

<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>deringo</groupId>
	<artifactId>testproject</artifactId>
	<version>1.0-SNAPSHOT</version>
	<name>testproject</name>
	<description></description>

	<properties>
		<maven.compiler.source>8</maven.compiler.source>
		<maven.compiler.target>8</maven.compiler.target>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
	</properties>

	<dependencies>
		<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
		<dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter-api</artifactId>
			<version>5.7.0</version>
			<scope>test</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.hamcrest/hamcrest -->
		<dependency>
			<groupId>org.hamcrest</groupId>
			<artifactId>hamcrest</artifactId>
			<version>2.2</version>
			<scope>test</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/io.smallrye/smallrye-rest-client -->
		<dependency>
			<groupId>io.smallrye</groupId>
			<artifactId>smallrye-rest-client</artifactId>
			<version>1.2.2</version>
		</dependency>
	</dependencies>

</project>
package deringo.testproject;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.junit.jupiter.api.Test;

public class TestJson {

	@Test
	public void testClientBuilderWorking() {
		Client client = ClientBuilder.newClient();
		WebTarget target = client.target("https://www.intensivregister.de/api/public/intensivregister");
		Response response = target.request(MediaType.APPLICATION_JSON).get();
		assertThat(response.getStatus(), is(200));
		JsonObject jo = response.readEntity(JsonObject.class);
		int rowCount = jo.getJsonNumber("rowCount").intValue();
		JsonArray ja = jo.getJsonArray("data");
		assertThat(ja.size(), is(rowCount));
		assertNotNull(ja.get(0).asJsonObject().getJsonObject("krankenhausStandort").getString("id"));

		ja.forEach(value -> 
				assertThat(
						value.asJsonObject().getString("id"),
						is(value.asJsonObject().getJsonObject("krankenhausStandort").getString("id"))
				));
	}

}
Categories
Java

PrimeFaces Template App

I need an easy way to show some database data of an existing application. The architecture and technic of the application is quite old and unconfortable, so I decided to setup a new project with a modern framework.

I need overview of data in a table, maybe with CSV or PDF file export. A chart to show the number of incoming data per time etc.
I want to use a framwork that provides components for this requirements, so I do not have to code much for things like paging, file export etc.
I one of my prior projects we used Java Server Faces, and so I came up to give PrimeFaces a try. They have a good ShowCase to show their components.

Unfortunatly it was a little bit more complex to setup the project than I thought at the beginning. No rocket science, but I took me some time for the initial setup, therefore I decided to extract this to a PrimeFaces Template Application to easily reuse it next time and uploaded it to GitHub.

Setup project

Created a new Maven project in Eclipse.
Added Eclipse Gitignore defaults from GitHub and target folder (created by Maven) to .gitignore file.
Added beans.xml, web.xml and index.xhtml files to project:


CDI

For CDI we need the beans.xml file. Nothing special, it just has to be there:

<?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_1_1.xsd"
	bean-discovery-mode="all">
</beans>

PrimeFaces Configuration

Minimum setup in web.xml, except of the explicit use of the Omega theme:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="4.0"
	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/web-app_4_0.xsd">

	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<context-param>
		<param-name>primefaces.THEME</param-name>
		<param-value>omega</param-value>
	</context-param>
	
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.xhtml</url-pattern>
	</servlet-mapping>

	<welcome-file-list>
		<welcome-file>index.xhtml</welcome-file>
	</welcome-file-list>
</web-app>

Dependencies

I want to use Tomcat and not a EE application server like Payara. Therefore I have to add JSF. And I want to use the current version, which is 2.3, so I have to add CDI (JBoss Weld) also.

Since this JSF version, the JSF managed bean facility @ManagedBean is DEPRECATED in in favour of CDI and CDI has become a REQUIRED dependency for JSF 2.3.

Of course PrimeFaces has to be added as dependency, currently in version 8.0 and PrimeFaces Themes.

<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>deringo</groupId>
	<artifactId>primefacestemplate</artifactId>
	<version>1.0-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>PrimeFacesTemplate</name>
	<description></description>

	<properties>
		<maven.compiler.source>15</maven.compiler.source>
		<maven.compiler.target>15</maven.compiler.target>
		<failOnMissingWebXml>false</failOnMissingWebXml>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
	</properties>

	<repositories>
		<repository>
			<id>prime-repo</id>
			<name>PrimeFaces Maven Repository</name>
			<url>http://repository.primefaces.org</url>
			<layout>default</layout>
		</repository>
	</repositories>

	<dependencies>
		<dependency>
			<groupId>org.apache.tomcat</groupId>
			<artifactId>tomcat</artifactId>
			<version>9.0.41</version>
			<type>pom</type>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax</groupId>
			<artifactId>javaee-api</artifactId>
			<version>8.0</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.enterprise</groupId>
			<artifactId>cdi-api</artifactId>
			<version>2.0</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.jboss.weld.servlet</groupId>
			<artifactId>weld-servlet</artifactId>
			<version>2.4.4.Final</version>
		</dependency>
		<dependency>
			<groupId>javax.faces</groupId>
			<artifactId>javax.faces-api</artifactId>
			<version>2.3</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.glassfish</groupId>
			<artifactId>javax.faces</artifactId>
			<version>2.3.0</version>
		</dependency>
		<dependency>
			<groupId>org.omnifaces</groupId>
			<artifactId>omnifaces</artifactId>
			<version>3.2</version>
		</dependency>
		<dependency>
			<groupId>org.primefaces</groupId>
			<artifactId>primefaces</artifactId>
			<version>8.0</version>
		</dependency>
		<dependency>
			<groupId>org.primefaces.themes</groupId>
			<artifactId>all-themes</artifactId>
			<version>1.0.10</version>
		</dependency>
		<dependency>
			<groupId>org.webjars.npm</groupId>
			<artifactId>primeflex</artifactId>
			<version>2.0.0</version>
		</dependency>
	</dependencies>

	<build>
		<finalName>PrimefacesTemplate</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.2</version>
				<configuration>
					<failOnMissingWebXml>false</failOnMissingWebXml>
					<warName>PrimefacesTemplate</warName>
					<wtpContextName>PrimefacesTemplate</wtpContextName>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

FlexGrid / PrimeFlex

Flex Grid CSS is a lightweight flex based responsive layout utility optimized for mobile phones, tablets and desktops. Flex Grid CSS is not included in PrimeFaces as it is provided by PrimeFlex, a shared grid library between PrimeFaces, PrimeNG and PrimeReact projects.

Add dependency for Webjar, so we do not need to download and copy the files in our project:

		<dependency>
			<groupId>org.webjars.npm</groupId>
			<artifactId>primeflex</artifactId>
			<version>2.0.0</version>
		</dependency>

Import PrimeFlex in index.xhtml:

<h:head>
  <h:outputStylesheet name="webjars/primeflex/2.0.0/primeflex.css" />
</h:head>

For the usage of PrimeFlex please have a look into the documentation.

PrimeIcons

The usage of PrimeIcons is well documented.
Just import the stylesheet and use them, example:

<h:head>
  <h:outputStylesheet name="primeicons/primeicons.css" library="primefaces" />
</h:head>

<h:body>
  <i class="pi pi-check"></i>
  <i class="pi pi-times"></i>
</h:body>

Categories
Development Java

Twitter4J

In my last post I created a twitter developer account. In this post I will access Twitter with a Java program.

Setup Eclipse Project

Create a new Maven Project:

Create a simple project (skip archetype selection).

Change JRE System Library from Java 1.5 to Java 1.8.

Add Twitter4J to Maven dependencies:

<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>de.kaulbach</groupId>
	<artifactId>twitter</artifactId>
	<version>1.0-SNAPSHOT</version>
	<packaging>jar</packaging>

	<properties>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.twitter4j</groupId>
			<artifactId>twitter4j-stream</artifactId>
			<version>4.0.7</version>
		</dependency>
	</dependencies>

	<build>
		<finalName>twitter</finalName>
	</build>

</project>

Configuration

Create a new file twitter4j.properties in folder src/main/resources with account properties from developer console:

oauth.consumerKey =       // your key (API key)
oauth.consumerSecret =    // your secret (API secret key)
oauth.accessToken =       // your token
oauth.accessTokenSecret = // your token secret

There are some other ways to configure (Java Code, Environment Variables, System Properties), see here

Java Code

Write a simple Code Example to show 7 Tweets with HashTag #Happy:

public class TwitterClient {

	public static void main(String[] args) throws Exception {
		Twitter twitter = TwitterFactory.getSingleton();
	    Query query = new Query("#Happy");
	    query.setCount(7);
	    QueryResult result = twitter.search(query);
	    for (Status status : result.getTweets()) {
	    	System.out.println("--");
	        System.out.println("@" + status.getUser().getScreenName() + ":" + status.getText());
	    }
	    System.out.println("----------------------------------------");
	}
}

Change code to show Tweets of Pope Francis with God in it:


Query query = new Query("from:Pontifex God");

Categories
Development

Twitter Developer Account

Everyone is talking about and on Twitter. Mostly every Tweet is public and pullable, this makes Twitter a gold mine of data (or a pile of mud, reading some of the Tweets).

I heard, with a Twitter Developer Account you can do a thing or two, so let's try this.

Twitter Developer Account

  1. Login or create a Twitter account at: https://apps.twitter.com/.
  2. Create a new app (button on the top right):
  1. Apply for a Twitter developer account
  1. You have to answer some questions, but finally:
  1. After confirming the email you can create your first Twitter App.
  2. It starts to give it a name
  1. You will be honoured with three secret keys: API key, API secret key and the Bearer token
  1. Give it a try! (really, do it)
  1. Next try: type in the curl command in your command line:
curl -X GET -H "Authorization: Bearer <SECRET_BEARER_TOKEN>" "https://api.twitter.com/2/tweets/440322224407314432?expansions=attachments.media_keys,author_id"

{"data":{"text":"If only Bradley's arm was longer. Best photo ever. #oscars http://t.co/C9U5NOtGap","id":"440322224407314432","attachments":{"media_keys":["3_440322224092745728"]},"author_id":"15846407"},"includes":{"media":[{"media_key":"3_440322224092745728","type":"photo"}],"users":[{"id":"15846407","name":"Ellen DeGeneres","username":"TheEllenShow"}]}}
  1. Next stop: The Developer Portal Dashboard

Documentation

The official Twitter API v2 Documentation seems to be a good point to start: https://developer.twitter.com/en/docs/twitter-api/early-access

Playground

Try to use the User lookup from the command line:

curl -X GET -H "Authorization: Bearer <SECRET_BEARER_TOKEN>" "https://api.twitter.com/2/users/by?usernames=twitterdev,twitterapi,adsapi&user.fields=created_at&expansions=pinned_tweet_id&tweet.fields=author_id,created_at"
{"data":[{"name":"Twitter Dev","pinned_tweet_id":"1293593516040269825","created_at":"2013-12-14T04:35:55.000Z","username":"TwitterDev","id":"2244994945"},{"name":"Twitter API","pinned_tweet_id":"1293595870563381249","created_at":"2007-05-23T06:01:13.000Z","username":"TwitterAPI","id":"6253282"},{"name":"Twitter Ads API","created_at":"2013-02-27T20:01:12.000Z","username":"AdsAPI","id":"1225933934"}],"includes":{"tweets":[{"author_id":"2244994945","id":"1293593516040269825","created_at":"2020-08-12T17:01:42.000Z","text":"It's finally here! \uD83E\uDD41 Say hello to the new #TwitterAPI.\n\nWe're rebuilding the Twitter API v2 from the ground up to better serve our developer community. And today's launch is only the beginning.\n\nhttps://t.co/32VrwpGaJw https://t.co/KaFSbjWUA8"},{"author_id":"6253282","id":"1293595870563381249","created_at":"2020-08-12T17:11:04.000Z","text":"Twitter API v2: Early Access released\n\nToday we announced Early Access to the first endpoints of the new Twitter API!\n\n#TwitterAPI #EarlyAccess #VersionBump https://t.co/g7v3aeIbtQ"}]}}

Try to use the Tweets lookup from the command line:

curl -X GET -H "Authorization: Bearer <SECRET_BEARER_TOKEN>" "https://api.twitter.com/2/tweets?ids=1228393702244134912,1227640996038684673,1199786642791452673&tweet.fields=created_at&expansions=author_id&user.fields=created_at"
{"data":[{"created_at":"2020-02-14T19:00:55.000Z","text":"What did the developer write in their Valentine's card?\n  \nwhile(true) {\n    I = Love(You);  \n}","id":"1228393702244134912","author_id":"2244994945"},{"created_at":"2020-02-12T17:09:56.000Z","text":"Doctors: Googling stuff online does not make you a doctor\n\nDevelopers: https://t.co/mrju5ypPkb","id":"1227640996038684673","author_id":"2244994945"},{"created_at":"2019-11-27T20:26:41.000Z","text":"C#","id":"1199786642791452673","author_id":"2244994945"}],"includes":{"users":[{"id":"2244994945","username":"TwitterDev","name":"Twitter Dev","created_at":"2013-12-14T04:35:55.000Z"}]}}

Making things a little bit more comfortable:

export BEARER_TOKEN=<SECRET_BEARER_TOKEN>

Search for the recently posted Tweets with Hashtag Corona in german language:

curl -X GET -H "Authorization: Bearer $BEARER_TOKEN" "https://api.twitter.com/1.1/search/tweets.json?q=%%23Corona&lang=de&result_type=recent"
Categories
Linux

NFS4

In my post to NFS I decribed how to create and attach a NFS folder.

Last week a colleague asked me to double check the version of this NS folder on the client. It turns out, that it was NFS3 only and not NFS4.

Interestingly this depends on the file permissions of the parent folder. The parend folder has to be read- and executable for others.

myAppServer1 – Server

chmod o+rx /app/myApp
exportfs -r
exportfs -s

myAppServer2 – Client

umount /app/myApp/uploads
mount /app/myApp/uploads
mount
-> myAppServer1.mynetwork.net:/app/myApp/uploads on /misc/myapp_uploads type nfs4