Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions .github/workflows/github_actions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# This is a basic workflow to help you get started with Actions

name: github actions for devon4j
env:
ORG: "devonfw"
REPO_SOURCE: "devon4j"
REPO_DEST: "devon4j.wiki"
REPO_CONSOLIDATE: "devonfw-guide"
GH_REPO_SOURCE: "github.com/${ORG}/${REPO_SOURCE}.git"
GH_REPO_DEST: "github.com/${ORG}/${REPO_DEST}.git"
GH_REPO_CONSOLIDATE: "github.com/${ORG}/${REPO_CONSOLIDATE}.git"

# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the develop branch
push:
branches: [ develop ]
pull_request:
branches: [ develop ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "include"
include:
# The type of runner that the job will run on
runs-on: ubuntu-18.04

# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository
- uses: actions/checkout@v2

- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: '11'

- name: Build
run: |
mvn install && ([[ $TRAVIS_BRANCH != "develop" ]] || [[ $TRAVIS_PULL_REQUEST != "false" ]] || mvn --settings .mvn/settings.xml -DskipTests=true -Darchetype.test.skip=true deploy)

- name: Documentation
run: |
cd ..
git clone https://${GH_REPO_DEST}
git clone https://${GH_REPO_CONSOLIDATE}
yes | cp -rf ${REPO_SOURCE}/documentation/* ${REPO_DEST}/
cd ${REPO_DEST}
grep -lr "link:[a-zA-Z0-9_.-]*.asciidoc.*" .| xargs -r sed -i "s/.asciidoc//g"
|
if git diff-index --quiet HEAD && [ ! -n "$(git status -s)" ]; then
set +e
pkill -9 -P $$ &> /dev/null || true
exit 0
else
git config user.email ${EMAIL}
git config user.name ${USER}
git status
git add .
git commit -m "${REPO_SOURCE} documentation | Travis CI build number $TRAVIS_BUILD_NUMBER"
git remote add origin-wiki "https://${USER}:${GITHUB_TOKEN}@${GH_REPO_DEST}"
git push origin-wiki master
cd ../${REPO_CONSOLIDATE}
if [ ! -d ${REPO_DEST} ]; then git submodule add https://${GH_REPO_DEST}; fi;
git submodule init
git submodule update --recursive --remote
cd ${REPO_DEST}
git checkout master
git pull
cd ..
git add .
git commit -m "${REPO_SOURCE} documentation | Travis CI build number $TRAVIS_BUILD_NUMBER"
git remote add origin-wiki "https://${USER}:${GITHUB_TOKEN}@${GH_REPO_CONSOLIDATE}"
git push origin-wiki master
fi
7 changes: 7 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
= devon4j

ATTENTION: You are on the `develop` branch.
This has been renamed to `master`.
The `develop` branch will not be maintained anymore.
It is only left here to avoid broken links to existing content.
Please update links to point to the `master` branch.
For details look at issue https://github.com/devonfw/devon4j/issues/320[#320].

Devon4j is the Java stack of http://devonfw.com[devonfw]. It allows you to build business applications (backends) using Java technology in a highly efficient and standardized way based on established best-practices. To build web-clients as frontend for a devon4j backend we recommend https://github.com/devonfw/devon4ng[devon4ng].

image:https://img.shields.io/github/license/devonfw/devon4j.svg?label=License["Apache License, Version 2.0",link=https://github.com/devonfw/devon4j/blob/develop/LICENSE.txt]
Expand Down
7 changes: 7 additions & 0 deletions documentation/Home.asciidoc
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
= devonfw for Java (devon4j)

ATTENTION: You are on the `develop` branch.
This has been renamed to `master`.
The `develop` branch will not be maintained anymore.
It is only left here to avoid broken links to existing content.
Please update links to point to the `master` branch.
For details look at issue https://github.com/devonfw/devon4j/issues/320[#320].

Welcome to the Java edition of devonfw. devon4j is documented by a platform guide (see the side-bar of this wiki) to be used in your projects.

You will find the latest stable versions of documents generated from this wiki here:
Expand Down
9 changes: 8 additions & 1 deletion documentation/alternative-microservice-netflix.asciidoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
:toc: macro
toc::[]

ATTENTION: You are on the `develop` branch.
This has been renamed to `master`.
The `develop` branch will not be maintained anymore.
It is only left here to avoid broken links to existing content.
Please update links to point to the `master` branch.
For details look at issue https://github.com/devonfw/devon4j/issues/320[#320].

== Microservices based on Netflix-Tools

Devonfw microservices approach is based on http://cloud.spring.io/spring-cloud-netflix/[Spring Cloud Netflix], that provides all the main components for microservices integrated within Spring Boot context.
Expand Down Expand Up @@ -687,4 +694,4 @@ public class FooClientHystrixFallback implements FooClient {
}

}
----
----
7 changes: 7 additions & 0 deletions documentation/architecture.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ toc::[]
:idprefix:
:idseparator: -

ATTENTION: You are on the `develop` branch.
This has been renamed to `master`.
The `develop` branch will not be maintained anymore.
It is only left here to avoid broken links to existing content.
Please update links to point to the `master` branch.
For details look at issue https://github.com/devonfw/devon4j/issues/320[#320].

There are many different views that are summarized by the term _architecture_. First, we will introduce the xref:key-principles[key principles] and xref:architecture-principles[architecture principles] of devonfw. Then, we will go into details of the the xref:application-architecture[architecture of an application].

== Key Principles
Expand Down
122 changes: 76 additions & 46 deletions documentation/coding-conventions.asciidoc
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
:toc: macro
toc::[]

ATTENTION: You are on the `develop` branch.
This has been renamed to `master`.
The `develop` branch will not be maintained anymore.
It is only left here to avoid broken links to existing content.
Please update links to point to the `master` branch.
For details look at issue https://github.com/devonfw/devon4j/issues/320[#320].

The code should follow general conventions for Java (see http://www.oracle.com/technetwork/java/namingconventions-139351.html[Oracle Naming Conventions], https://google.github.io/styleguide/javaguide.html[Google Java Style], etc.).We consider this as common sense and provide configurations for http://www.sonarqube.org/[SonarQube] and related tools such as http://checkstyle.sourceforge.net/[Checkstyle] instead of repeating this here.

== Naming
Besides general Java naming conventions, we follow the additional rules listed here explicitly:

* Always use short but speaking names (for types, methods, fields, parameters, variables, constants, etc.).
* Strictly avoid special characters in technical names (for files, types, fields, methods, properties, variables, database tables, columns, constraints, etc.). In other words only use Latin alpahnumeric ASCII characters with the common allowed technical separators for the accordign context (e.g. underscore) for technical names (even excluding whitespaces).
* For package segments and type names prefer singular forms (`CustomerEntity` instead of [line-through]`CustomersEntity`). Only use plural forms when there is no singular or it is really semantically required (e.g. for a container that contains multiple of such objects).
* Avoid having duplicate type names. The name of a class, interface, enum or annotation should be unique within your project unless this is intentionally desired in a special and reasonable situation.
* Avoid artificial naming constructs such as prefixes (`I*`) or suffixes (`*IF`) for interfaces.
Expand Down Expand Up @@ -53,81 +61,81 @@ With devonfw we experienced the same for the codebase (what is inside `src/main/
| ├──.common
| | ├──.api[.«detail»]
| | | ├──.link:guide-datatype.asciidoc[datatype]
| | | | └──.link:guide-datatype.asciidoc[«Datatype»]
| | | └──.link:guide-transferobject.asciidoc#bo[«BusinessObject»]
| | | | └──.link:guide-datatype.asciidoc[«Datatype»] (api)
| | | └──.link:guide-transferobject.asciidoc#bo[«BusinessObject»] (api)
| | └──.impl[.«detail»]
| | ├──.link:guide-configuration-mapping.asciidoc#mapping-advanced-configuration[«Aspect»ConfigProperties]
| | ├──.link:guide-json.asciidoc#custom-mapping[«Datatype»JsonSerializer]
| | └──.link:guide-json.asciidoc#custom-mapping[«Datatype»JsonDeserializer]
| | ├──.link:guide-configuration-mapping.asciidoc#mapping-advanced-configuration[«Aspect»ConfigProperties] (core)
| | ├──.link:guide-json.asciidoc#custom-mapping[«Datatype»JsonSerializer] (core)
| | └──.link:guide-json.asciidoc#custom-mapping[«Datatype»JsonDeserializer] (core)
| ├──.link:guide-dataaccess-layer.asciidoc[dataaccess]
| | ├──.api[.«detail»]
| | | ├──.link:guide-repository.asciidoc[repo]
| | | | └──.link:guide-repository.asciidoc#repository[«BusinessObject»Repository]
| | | ├──.link:guide-dao.asciidoc[dao] (alternative to repo)
| | | | └──.link:guide-dao.asciidoc#data-access-object[«BusinessObject»Dao] (alternative to Repository)
| | | └──.link:guide-jpa.asciidoc#entity[«BusinessObject»Entity]
| | | | └──.link:guide-repository.asciidoc#repository[«BusinessObject»Repository] (core)
| | | ├──.link:guide-dao.asciidoc[dao] (core) [alternative to repo]
| | | | └──.link:guide-dao.asciidoc#data-access-object[«BusinessObject»Dao] (core) [alternative to Repository]
| | | └──.link:guide-jpa.asciidoc#entity[«BusinessObject»Entity] (core)
| | └──.impl[.«detail»]
| | ├──.link:guide-dao.asciidoc[dao] (alternative to repo)
| | | └──.link:guide-dao.asciidoc#data-access-object[«BusinessObject»DaoImpl] (alternative to Repository)
| | └──.link:guide-jpa.asciidoc#entities-and-datatypes[«Datatype»AttributeConverter]
| | ├──.link:guide-dao.asciidoc[dao] (core) [alternative to repo]
| | | └──.link:guide-dao.asciidoc#data-access-object[«BusinessObject»DaoImpl] (core) [alternative to Repository]
| | └──.link:guide-jpa.asciidoc#entities-and-datatypes[«Datatype»AttributeConverter] (core)
| ├──.link:guide-logic-layer.asciidoc[logic]
| | ├──.api
| | | ├──.[«detail».]link:guide-transferobject.asciidoc[to]
| | | | ├──.link:guide-transferobject.asciidoc#to[«MyCustom»«To]
| | | | ├──.link:guide-jpa.asciidoc#embeddable[«DataStructure»Embeddable]
| | | | ├──.link:guide-transferobject.asciidoc#eto[«BusinessObject»Eto]
| | | | └──.link:guide-transferobject.asciidoc#cto[«BusinessObject»«Subset»Cto]
| | | | ├──.link:guide-transferobject.asciidoc#to[«MyCustom»«To] (api)
| | | | ├──.link:guide-jpa.asciidoc#embeddable[«DataStructure»Embeddable] (api)
| | | | ├──.link:guide-transferobject.asciidoc#eto[«BusinessObject»Eto] (api)
| | | | └──.link:guide-transferobject.asciidoc#cto[«BusinessObject»«Subset»Cto] (api)
| | | ├──.[«detail».]link:guide-usecase.asciidoc[usecase]
| | | | ├──.link:guide-usecase.asciidoc#find[UcFind«BusinessObject»]
| | | | ├──.link:guide-usecase.asciidoc#manage[UcManage«BusinessObject»]
| | | | └──.link:guide-usecase.asciidoc#custom[Uc«Operation»«BusinessObject»]
| | | └──.link:guide-logic-layer.asciidoc#component[«Component»]
| | | | ├──.link:guide-usecase.asciidoc#find[UcFind«BusinessObject»] (core)
| | | | ├──.link:guide-usecase.asciidoc#manage[UcManage«BusinessObject»] (core)
| | | | └──.link:guide-usecase.asciidoc#custom[Uc«Operation»«BusinessObject»] (core)
| | | └──.link:guide-logic-layer.asciidoc#component[«Component»] (core)
| | ├──.base
| | | └──.[«detail».]link:guide-usecase.asciidoc[usecase]
| | | └──.link:guide-usecase.asciidoc[Abstract«BusinessObject»Uc]
| | | └──.link:guide-usecase.asciidoc[Abstract«BusinessObject»Uc] (core)
| | └──.impl
| | ├──.[«detail».]link:guide-usecase.asciidoc[usecase]
| | | ├──.link:guide-usecase.asciidoc#find[UcFind«BusinessObject»Impl]
| | | ├──.link:guide-usecase.asciidoc#manage[UcManage«BusinessObject»Impl]
| | | └──.link:guide-usecase.asciidoc#custom[Uc«Operation»«BusinessObject»Impl]
| | └──.link:guide-logic-layer.asciidoc#component[«Component»Impl]
| | | ├──.link:guide-usecase.asciidoc#find[UcFind«BusinessObject»Impl] (core)
| | | ├──.link:guide-usecase.asciidoc#manage[UcManage«BusinessObject»Impl] (core)
| | | └──.link:guide-usecase.asciidoc#custom[Uc«Operation»«BusinessObject»Impl] (core)
| | └──.link:guide-logic-layer.asciidoc#component[«Component»Impl] (core)
| └──.link:guide-service-layer.asciidoc[service]
| ├──.api[.«detail»]
| | ├──.link:guide-rest.asciidoc[rest]
| | | └──.link:guide-rest.asciidoc#rest-service-api[«Component»RestService]
| | | └──.link:guide-rest.asciidoc#rest-service-api[«Component»RestService] (api)
| | └──.link:guide-soap.asciidoc[ws]
| | └──.link:guide-soap.asciidoc#web-service-api[«Component»WebService]
| | └──.link:guide-soap.asciidoc#web-service-api[«Component»WebService] (api)
| └──.impl[.«detail»]
| ├──.link:guide-jms.asciidoc[jms]
| | └──.link:guide-jms.asciidoc#jms-listener[«BusinessObject»JmsListener]
| | └──.link:guide-jms.asciidoc#jms-listener[«BusinessObject»JmsListener] (core)
| ├──.link:guide-rest.asciidoc[rest]
| | └──.link:guide-rest.asciidoc#rest-service-implementation[«Component»RestServiceImpl]
| | └──.link:guide-rest.asciidoc#rest-service-implementation[«Component»RestServiceImpl] (core)
| └──.link:guide-soap.asciidoc[ws]
| └──.link:guide-soap.asciidoc#web-service-implementation[«Component»WebServiceImpl]
| └──.link:guide-soap.asciidoc#web-service-implementation[«Component»WebServiceImpl] (core)
├──.link:guide-component.asciidoc#general-component[general]
│ ├──.common
│ | ├──.api
| | | ├──.to
| | | | ├──.AbstractSearchCriteriaTo
| | | | ├──.AbstractSearchCriteriaTo (api)
| | | └──.ApplicationEntity
│ | ├──.base
| | | └──.AbstractBeanMapperSupport
| | | └──.AbstractBeanMapperSupport (core)
│ | └──.impl
│ | ├──.config
│ | | └──.ApplicationObjectMapperFactory
│ | | └──.ApplicationObjectMapperFactory (core)
│ | └──.security
│ | └──.ApplicationWebSecurityConfig
│ | └──.ApplicationWebSecurityConfig (core)
│ ├──.dataaccess
│ | └──.api
| | └──.ApplicationPersistenceEntity
| | └──.ApplicationPersistenceEntity (core)
│ ├──.logic
│ | └──.base
| | ├──.AbstractComponentFacade
| | ├──.AbstractLogic
| | └──.AbstractUc
| | ├──.AbstractComponentFacade (core)
| | ├──.AbstractLogic (core)
| | └──.AbstractUc (core)
| └──.service
| └──...
└──.SpringBootApp
└──.SpringBootApp (core)
----

== Code Tasks
Expand Down Expand Up @@ -179,6 +187,7 @@ Resources such as streams (`InputStream`, `OutputStream`, `Reader`, `Writer`) or
Closing streams and other such resources is error prone. Have a look at the following example:
[source,java]
----
// bad
try {
InputStream in = new FileInputStream(file);
readData(in);
Expand All @@ -191,6 +200,7 @@ try {
The code above is wrong as in case of an `IOException` the `InputStream` is not properly closed. In a server application such mistakes can cause severe errors that typically will only occur in production. As such resources implement the `AutoCloseable` interface you can use the `try-with-resource` syntax to write correct code. The following code shows a correct version of the example:
[source,java]
----
// fine
try (InputStream in = new FileInputStream(file)) {
readData(in);
} catch (IOException e) {
Expand Down Expand Up @@ -218,6 +228,7 @@ However, these new features can also be misused or led to code that is hard to r
+
[source,java]
----
// bad
collection.stream().map(x -> {
Foo foo = doSomething(x);
...
Expand All @@ -229,6 +240,7 @@ This style makes the code hard to read and debug. Never do that! Instead, extrac
+
[source,java]
----
// fine
collection.stream().map(this::convertToFoo).collect(Collectors.toList());
----
. Do not use `parallelStream()` in general code (that will run on server side) unless you know exactly what you are doing and what is going on under the hood. Some developers might think that using parallel streams is a good idea as it will make the code faster. However, if you want to do performance optimizations talk to your technical lead (architect). Many features such as security and transactions will rely on contextual information that is associated with the current thread. Hence, using parallel streams will most probably cause serious bugs. Only use them for standalone (CLI) applications or for code that is just processing large amounts of data.
Expand All @@ -250,32 +262,31 @@ set.stream().peek(...).collect(Collectors.toList()) // fine
+
[source,java]
----
(a,b,c) -> a.toString() + Float.toString(b) + Arrays.toString(c) // fine
(String a, Float b, Byte[] c) -> a.toString() + Float.toString(b) + Arrays.toString(c) // bad
(a,b,c) -> a.toString() + Float.toString(b) + Arrays.toString(c) // fine

Collections.sort(personList, (p1, p2) -> p1.getSurName().compareTo(p2.getSurName())); // fine
Collections.sort(personList, (Person p1, Person p2) -> p1.getSurName().compareTo(p2.getSurName())); // bad

Collections.sort(personList, (p1, p2) -> p1.getSurName().compareTo(p2.getSurName())); // fine
----
. Avoid Return Braces and Statement
+
[source,java]
----
a -> a.toString(); // fine
a -> { return a.toString(); } // bad
a -> a.toString(); // fine
----
. Avoid Parentheses with Single Parameter
+
[source,java]
----
a -> a.toString(); // fine
(a) -> a.toString(); // bad
a -> a.toString(); // fine
----
. Avoid if/else inside foreach method. Use Filter method & comprehension
+
[source,java]
----
Bad
// bad
static public Iterator<String> TwitterHandles(Iterator<Author> authors, string company) {
final List result = new ArrayList<String> ();
foreach (Author a : authors) {
Expand All @@ -291,7 +302,7 @@ static public Iterator<String> TwitterHandles(Iterator<Author> authors, string c
+
[source,java]
----
Fine
// fine
public List<String> twitterHandles(List<Author> authors, String company) {
return authors.stream()
.filter(a -> null != a && a.getCompany().equals(company))
Expand Down Expand Up @@ -328,3 +339,22 @@ Avoid unnecessary strong bindings:
* In APIs for input (=parameters) always consider to make little assumptions:
** prefer `Collection` over `List` or `Set` where the difference does not matter (e.g. only use `Set` when you require uniqueness or highly efficient `contains`)
** consider preferring `Collection<? extends Foo>` over `Collection<Foo>` when `Foo` is an interface or super-class

=== Prefer primitive boolean
Unless in rare cases where you need to allow a flag being `null` avoid using the object type `Boolean`.
[source,java]
----
// bad
public Boolean isEmpty {
return size() == 0;
}
----
Instead always use the primitive `boolean` type:
[source,java]
----
// fine
public boolean isEmpty {
return size() == 0;
}
----
The only known excuse is for flags in link:guide-jpa.asciidoc#embeddable[embeddable types] due to limitations of hibernate.
Loading