I'm quite fond of Event-driven architecture, so to no surprise, I like vert.x's EventBus and its ability to enable polyglot programming. So it is time to have a closer look
Dem Volk aufs Maul geschaut
(That's a word play on Martin Luther loosly translated as "Watch them how they talk")
I wanted to know, what exactly is happening "on the wire", without disrupting the regular flow. Turns out, there is an easy way to do this. The vert.x EventBus provides the methods addOutboundInterceptor and addInboundInterceptor that provide you with access to a Handler with a DeliveryContext.
From there you can get to the Message or directly the message's body. So I took it for a spin in conjunction with a Websocket. This allows me to watch as the messages flow through:
final HttpServer server = this.vertx.createHttpServer();
server.websocketHandler(this::handlerWebsockets);
Read more
Posted by Stephan H Wissel on 28 April 2020
|
categories: Javavert.x
It is 2020, JSON is supposed to have won, with a challenger in sight. XML with its fine distinction between Elements, Attributes and clear ownership demarked by name spaces, was supposed to be gone. But OData made it necessary to look again, as did CalDAV
Out into the OutputStream
The initial version was introduced in the context of XAgents which mandated an OutputStream. I find that adequate and useful, so I kept that. If you just want a String, a ByteArrayOutputStream will do quite nicely
Fluent methods
The big change to the revamped version is the addition of a fluent API. Each method call returns the object instance itself, so you can chain your document creation to look modern (and type less)
Namespace and attributes
Originally I though "simple" would be sufficient to create Elements only. But as time goes by one starts to appreciate name spaces and Attributes, so I added support for these too. To keep things simple: once we specify the namespace at the beginning of the document, we can simply refer to it by its alias name.
A sample:
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final SimpleXMLDoc doc = new SimpleXMLDoc(out);
doc.addNamespace("X", "https://xmen.org")
.addNamespace("", "https://whyOhWhy.com/xml")
.setXmlStyleSheet("somestle.xslt")
.openElement("Endpoints")
.openElement(doc.element("X:Endpoint")
.addAttribute("name", "A Name")
.addAttribute("url", "http://anywhere/")
.addAttribute("meta", "meta not metta"))
.closeElement(1)
.addSimpleElement("description", "Something useful")
.closeDocument();
System.out.println(out.toString());
Key methods
addNamespace: adds one name space and establishes the alias. To keep it simple, namespaces are defined only at the beginning fo the document
setXmlStyleSheet: Same here, needs to be defined at the beginning - after all this class streams the result and stylesheets only start at the beginning
OpenElement starts a new XML Element. When provided with a string, it is an attribute free element, that can include the namespace abbreviation. When using a doc.element, we can add attributes
addSimpleElement: add an element, its String content and close it
closeElement: write out a number of closing tags. It deliberately uses number of tags and not tag names, so you don't need to track the names you have opened. Ensures that XML stays valid
closeDocument: closes all remaining Elements in the correct sequence and closes the document. Can be called once only
Check the full source code for details
As usual YMMV
Posted by Stephan H Wissel on 13 April 2020
|
categories: JavaXML
One of the security mechanism for AJAX calls is CORS (Cross-Origin Resource sharing), where a server advice a browser if it can request resources from it, coming from a different domain.
It is then up to the browser to heed that advice. To complicate matters: when the browser wants to POST data (or other similar operations), it will go through a preflight request adding to site latency.
I have to admit, I never fully understood the rationale, since only browsers adhere to CORS, any webserver, Postman or CURL ignore CORS happily.
None, One or All, but not Some
There's another trouble with CORS: The specification only allows for no-access, all-access (using * as value for Access-Control-Allow-Origin, with restrictions) or one specific domain, but not a list of domains.
Mozilla writes
Limiting the possible Access-Control-Allow-Origin values to a set of allowed origins requires code on the server side to check the value of the Origin request header, compare that to a list of allowed origins, and then if the Origin value is in the list, to set the Access-Control-Allow-Origin value to the same value as the Origin value.
Read more
Posted by Stephan H Wissel on 07 April 2020
|
3 comments
|
categories: SalesforceSingapore
Maven is to Java what npm is to JavaScript. It can be a harsh mistress or your best companion. It depends
Beyond dependencies and builds
Maven removes the need to download and manages your dependencies. Unfortunately it doesn't come with mvn install <packagename> like npm (or I haven't learned that yet), so keeping that pom.xml current is a little PITA. However once we make peace with it, the power of plugins makes development in auto-pilot a breeze. Some of the things you can do:
- Generate a project site
- Generate various reports: code quality, code coverage
- Run unit tests
Check out the complete list to get an idea. I'm specifically fond of the site generation capability. It allows us to keep your documentation in the same repository as the project, so we have one place less to worry about.
We simply add /src/site/ to our project and content can be created in multiple formats. My favorite one is Markdown. Besides my handcrafted pages, I generate reports:
- Issue management
- Licenses
- Plugins
- Source code location
- Team
- JavaDoc
- PMD and CPD
- Surefire (Test results) and JaCoCo (Test coverage)
All this involved a bit of boilerplate in the pom.xml so I keep a template around
that I copy into any new pom.xml file. On special fancy I use: I extracted all version numbers from plugin and dependencies and keep them in an alphabetical sorted property section. This way I avoid to have multiple versions of related dependencies around. Enjoy!
<properties>
<!-- Dependency Versions -->
<darvino.version>2.5.0</darvino.version>
<domino.jna.version>0.9.26</domino.jna.version>
<domino.version>10.0.1</domino.version>
<expiringmap.version>0.5.9</expiringmap.version>
<flexmark.version>0.60.2</flexmark.version>
<grpc.version>1.24.0</grpc.version>
<gson.version>2.8.5</gson.version>
<guava.version>28.2-jre</guava.version>
<ibm.commons.version>9.0.0</ibm.commons.version>
<icu4j.version>65.1</icu4j.version>
<javasimon.version>4.2.0</javasimon.version>
<java.version>1.8</java.version>
<joda.version>2.10</joda.version>
<junit.platform.version>1.5.2</junit.platform.version>
<junit.jupiter.version>5.6.0</junit.jupiter.version>
<log4j.version>2.12.1</log4j.version>
<lorem.version>2.1</lorem.version>
<micrometer.version>1.3.5</micrometer.version>
<mustache.version>0.9.5</mustache.version>
<mockito.version>3.3.3</mockito.version>
<netty.ssl.version>2.0.30.Final</netty.ssl.version>
<pmd.version>6.22.0</pmd.version>
<saxon.version>10.0</saxon.version>
<slf4j.version>1.7.28</slf4j.version>
<yaml.version>1.25</yaml.version>
<vertx.version>4.0.0-milestone4</vertx.version>
<!-- Maven Versions -->
<maven.version>[3.6,)</maven.version>
<!-- Plugin Versions -->
<eclipse.plugin.version>2.10</eclipse.plugin.version>
<maven.compiler.plugin.version>3.8.1</maven.compiler.plugin.version>
<maven.enforcer.plugin.version>3.0.0-M3</maven.enforcer.plugin.version>
<maven.jacoco.plugin.version>0.8.5</maven.jacoco.plugin.version>
<maven.jar.plugin.version>3.2.0</maven.jar.plugin.version>
<maven.javadoc.plugin.version>3.1.1</maven.javadoc.plugin.version>
<maven.jxr.plugin.version>3.0.0</maven.jxr.plugin.version>
<maven.project.info.reports.plugin.version>3.0.0</maven.project.info.reports.plugin.version>
<maven.resources.plugin.version>3.1.0</maven.resources.plugin.version>
<maven.site.plugin.version>3.8.2</maven.site.plugin.version>
<maven.source.plugin.version>3.2.0</maven.source.plugin.version>
<maven.surefire.plugin.version>3.0.0-M4</maven.surefire.plugin.version>
<os.maven.plugin.version>1.6.2</os.maven.plugin.version>
<pegdown.doclet.version>1.3</pegdown.doclet.version>
<pmd.plugin.version>3.12.0</pmd.plugin.version>
<protobuf.maven.plugin.version>0.6.1</protobuf.maven.plugin.version>
<shade.version>3.2.1</shade.version>
<versions.maven.plugin.version>2.7</versions.maven.plugin.version>
<!-- Miscellaneous settings -->
<project.autorelease>true</project.autorelease>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<finalName>${project.artifactId}-${project.version}</finalName>
</properties>
<prerequisites>
<maven>${maven.version}</maven>
</prerequisites>
<organization>
<name>HCL Labs</name>
<url>[FIXME: URL HERE]</url>
</organization>
<ciManagement>
<system>CircleCI</system>
<url>[FIXME: Link to CI]</url>
</ciManagement>
<issueManagement>
<system>JIRA</system>
<url>[FIXME: URL to Issue tracker]</url>
</issueManagement>
<developers>
</developer>
<developer>
<name>Stephan H. Wissel</name>
<roles>
<role>Architect</role>
<role>Developer</role>
</roles>
<url>https://github.com/stwissel</url>
</developer>
</developers>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>manual</distribution>
</license>
</licenses>
<scm>
<developerConnection>scm:git:[FIXME: GIT URL]</developerConnection>
</scm>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>${maven.enforcer.plugin.version}</version>
<executions>
<execution>
<id>enforce-maven</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>${maven.version}</version>
</requireMavenVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven.source.plugin.version}</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>${eclipse.plugin.version}</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven.javadoc.plugin.version}</version>
<configuration>
<doclet>ch.raffael.doclets.pegdown.PegdownDoclet</doclet>
<docletArtifact>
<groupId>ch.raffael.pegdown-doclet</groupId>
<artifactId>pegdown-doclet</artifactId>
<version>1.3</version>
</docletArtifact>
<useStandardDocletOptions>false</useStandardDocletOptions>
<failOnError>false</failOnError>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${maven.jacoco.plugin.version}</version>
<configuration>
<excludes>
<exclude>[FIXME: Do we need to exclude files from tests?]</exclude>
</excludes>
</configuration>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven.surefire.plugin.version}</version>
<configuration>
<includes>
<include>**/*Test.java</include>
<include>**/*Tests.java</include>
<include>**/*TestCase.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>${versions.maven.plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>${maven.project.info.reports.plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>${maven.site.plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>${pmd.plugin.version}</version>
<configuration>
<linkXRef>true</linkXRef>
<targetJdk>${java.version}</targetJdk>
</configuration>
<dependencies>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-core</artifactId>
<version>${pmd.version}</version>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-java</artifactId>
<version>${pmd.version}</version>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-javascript</artifactId>
<version>${pmd.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<!-- This allows to use markdown in JavaDoc -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven.javadoc.plugin.version}</version>
<configuration>
<doclet>ch.raffael.doclets.pegdown.PegdownDoclet</doclet>
<docletArtifact>
<groupId>ch.raffael.pegdown-doclet</groupId>
<artifactId>pegdown-doclet</artifactId>
<version>${pegdown.doclet.version}</version>
</docletArtifact>
<useStandardDocletOptions>false</useStandardDocletOptions>
<failOnError>false</failOnError>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>${pmd.plugin.version}</version>
<configuration>
<linkXRef>true</linkXRef>
<targetJdk>${java.version}</targetJdk>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>${maven.surefire.plugin.version}</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${maven.jacoco.plugin.version}</version>
<reportSets>
<reportSet>
<reports>
<!-- select non-aggregate reports -->
<report>report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>${maven.jxr.plugin.version}</version>
</plugin>
</plugins>
</reporting>
<dependencies>
<!-- Test dependencies -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
Check for FIXME: entries to find the spots that need updating. Maven has a task to check from time to time which of the depdendencies have newer version. You can run mvn versions:display-dependency-updates to find out what can be updated
As usual YMMV!
Posted by Stephan H Wissel on 06 April 2020
|
categories: JavaMavenWebDevelopmentXML