From: Kai Moritz Date: Fri, 19 Dec 2025 10:37:52 +0000 (+0100) Subject: Spezial-Menü für die Untersektionen von `blog` anstatt für `blog` selbst X-Git-Tag: frontend--hugo--rebase--2025-12-21--19-20~7 X-Git-Url: https://juplo.de/gitweb/?a=commitdiff_plain;h=049de2d2fbcd7d2225753bc20335ae75860bdfd6;p=website Spezial-Menü für die Untersektionen von `blog` anstatt für `blog` selbst -- MOVE --- diff --git a/content/blog/2013/article.html b/content/blog/2013/article.html new file mode 100644 index 00000000..050c2d01 --- /dev/null +++ b/content/blog/2013/article.html @@ -0,0 +1,302 @@ +--- +categories: + - jetty + - less + - maven + - wro4j +date: "2013-12-06T10:58:17+00:00" +title: Combining jetty-maven-plugin and wro4j-maven-plugin for Dynamic Reloading of LESS-Resources +url: /combining-jetty-maven-plugin-and-wro4j-maven-plugin-for-dynamic-reloading-of-less-resources/ +--- +
+
+
+

Combining jetty-maven-plugin and wro4j-maven-plugin for Dynamic Reloading of LESS-Resources

+ +
+
+

Ever searched for a simple configuration, that lets you use your jetty-maven-plugin as you are used to, while working with LESS to simplify your stylesheets?

+

You cannot do both, use the Client-side mode of LESS to ease development and use the lesscss-maven-plugin to automatically compile the LESS-sources into CSS for production. That does not work, because your stylesheets must be linked in different ways if you are switching between the client-side mode – which is best for development – and the pre-compiled mode – which is best for production. For the client-side mode you need something like:

+
  
+  <link rel="stylesheet" type="text/css" href="styles.css" />
+  <script src="less.js" type="text/javascript"></script>
+  
+          
+

While, for the pre-compiled mode, you want to link to your stylesheets as usual, with:

+
  
+  <link rel="stylesheet" type="text/css" href="styles.css" />
+  
+          
+

While looking for a solution to this dilemma, I stumbled accross wro4j. Originally intended, to speed up page-delivery by combining and minimizing multiple resources into one through the use of a servlet-filter, this tool also comes with a maven-plugin, that let you do the same offline, while compiling your webapp.

+

The idea is, to use the wro4j-maven-plugin to compile and combine your LESS-sources into CSS for production and to use the wro4j filter, to dynamically deliver the compiled CSS while developing. This way, you do not have to alter your HTML-code, when switching between development and production, because you always link to the CSS-files.

+

So, lets get dirty!

+

Step 1: Configure wro4j

+

First, we configure wro4j, like as we want to use it to speed up our page. The details are explained and linked on wro4j’s Getting-Started-Page. In short, we just need two files: wro.xml and wro.properties.

+

wro.xml

+

wro.xml tells wro4j, which resources should be combined and how the result should be named. I am using the following configuration to generate all LESS-Sources beneath base/ into one CSS-file called base.css:

+
  
+  <groups xmlns="http://www.isdc.ro/wro">
+    <group name="base">
+      <css>/css/base/*.css</css>
+    </group>
+  
+          
+

wro4j looks for /css/base/*.css inside the root of the web-context, which is equal to src/main/webapp in a normal maven-project. There are other ways to specifie the resources, which enable you to store them elswhere. But this approach works best for our goal, because the path is understandable for both: the wro4j servlet-filter, we are configuring now for our development-environment, and the wro4j-maven-plugin, that we will configure later for build-time compilation.

+

wro.properties

+

wro.properties in short tells wro4j, how or if it should convert the combined sources and how it should behave. I am using the following configuration to tell wro4j, that it should convert *.css-sources into CSS and do that on every request:

+
  
+  preProcessors=less4j
+  disableCache=true
+  
+          
+

You can do a lot more here. There are countless configuration options to fine-tune the behaviour of wro4j. The disableCache=true is crucial, because we would not see the changes take effect when developing with jetty-maven-plugin later on. You can also do much more with your resources here, for example minimizing. But for our goal, we are now only intrested in the compilation of our LESS-sources.

+

Step 2: Configure the wro4j servlet-filter

+

Configuring the filter in the web.xml is easy. It is explained in wro4j’s installation-insctuctions. But the trick is, that we do not want to configure that filter for the production-version of our webapp, because we want to compile the resources offline, when the webapp is build. To acchieve this, we can use the <overrideDescriptor>-Parameter of the jetty-maven-plugin.

+

<overrideDescriptor>

+

This parameter lets you specify additional configuration options for the web.xml of your webapp. I am using the following configuration for my jetty-maven-plugin:

+
  
+  <plugin>
+    <groupId>org.eclipse.jetty</groupId>
+    <artifactId>jetty-maven-plugin</artifactId>
+    <configuration>
+      <webApp>
+        <overrideDescriptor>${project.basedir}/src/test/resources/jetty-web.xml</overrideDescriptor>
+      </webApp>
+    </configuration>
+    <dependencies>
+      <dependency>
+        <groupId>ro.isdc.wro4j</groupId>
+        <artifactId>wro4j-core</artifactId>
+        <version>${wro4j.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>ro.isdc.wro4j</groupId>
+        <artifactId>wro4j-extensions</artifactId>
+        <version>${wro4j.version}</version>
+        <exclusions>
+          <exclusion>
+              <groupId>javax.servlet</groupId>
+              <artifactId>servlet-api</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>org.apache.commons</groupId>
+              <artifactId>commons-lang3</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>commons-io</groupId>
+              <artifactId>commons-io</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>commons-pool</groupId>
+              <artifactId>commons-pool</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>org.springframework</groupId>
+              <artifactId>spring-web</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>com.google.code.gson</groupId>
+              <artifactId>gson</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>com.google.javascript</groupId>
+              <artifactId>closure-compiler</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>com.github.lltyk</groupId>
+              <artifactId>dojo-shrinksafe</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>org.jruby</groupId>
+              <artifactId>jruby-core</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.jruby</groupId>
+            <artifactId>jruby-stdlib</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>org.jruby</groupId>
+              <artifactId>jruby-stdlib</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>me.n4u.sass</groupId>
+              <artifactId>sass-gems</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>nz.co.edmi</groupId>
+              <artifactId>bourbon-gem-jar</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>org.codehaus.gmaven.runtime</groupId>
+              <artifactId>gmaven-runtime-1.7</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>org.webjars</groupId>
+              <artifactId>jshint</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>org.webjars</groupId>
+              <artifactId>less</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>org.webjars</groupId>
+              <artifactId>emberjs</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>org.webjars</groupId>
+              <artifactId>handlebars</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>org.webjars</groupId>
+              <artifactId>coffee-script</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>org.webjars</groupId>
+              <artifactId>jslint</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>org.webjars</groupId>
+              <artifactId>json2</artifactId>
+          </exclusion>
+          <exclusion>
+              <groupId>org.webjars</groupId>
+              <artifactId>jquery</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+    </dependencies>
+  </plugin>
+  
+          
+

The dependencies to wro4j-core and wro4j-extensions are needed by jetty, to be able to enable the filter defined below. Unfortunatly, one of the transitive dependencies of wro4j-extensions triggers an uggly error when running the jetty-maven-plugin. Therefore, all unneeded dependencies of wro4j-extensions are excluded, as a workaround for this error/bug.

+

jetty-web.xml

+

And my jetty-web.xml looks like this:

+
  
+  <?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_2_5.xsd"
+    version="2.5">
+    <filter>
+      <filter-name>wro</filter-name>
+      <filter-class>ro.isdc.wro.http.WroFilter</filter-class>
+    </filter>
+    <filter-mapping>
+      <filter-name>wro</filter-name>
+      <url-pattern>*.css</url-pattern>
+    </filter-mapping>
+  </web-app>
+  
+          
+

The filter processes any URI’s that end with .css. This way, the wro4j servlet-filter makes base.css available under any path, because for exampl /base.css, /css/base.css and /foo/bar/base.css all end with .css.

+

This is all, that is needed to develop with dynamically reloadable compiled LESS-resources. Just fire up your browser and browse to /what/you/like/base.css. (But do not forget to put some LESS-files in src/main/webapp/css/base/ first!)

+

Step 3: Install wro4j-maven-plugin

+

All that is left over to configure now, is the build-process. If you would build and deploy your webapp now, the CSS-file base.css would not be generated and the link to your stylesheet, that already works in our jetty-maven-plugin environment would point to a 404. Hence, we need to set up the wro4j-maven-plugin. I am using this configuration:

+
  
+  <plugin>
+    <groupId>ro.isdc.wro4j</groupId>
+    <artifactId>wro4j-maven-plugin</artifactId>
+    <version>${wro4j.version}</version>
+    <configuration>
+      <wroManagerFactory>ro.isdc.wro.maven.plugin.manager.factory.ConfigurableWroManagerFactory</wroManagerFactory>
+      <cssDestinationFolder>${project.build.directory}/${project.build.finalName}/css/</cssDestinationFolder>
+    </configuration>
+    <executions>
+      <execution>
+        <phase>package</phase>
+        <goals>
+          <goal>run</goal>
+        </goals>
+      </execution>
+    </executions>
+  </plugin>
+  
+          
+

I connected the run-goal with the package-phase, because the statically compiled CSS-file is needed only in the final war. The ConfigurableWroManagerFactory tells wro4j, that it should look up further configuration options in our wro.properties-file, where we tell wro4j, that it should compile our LESS-resources. The <cssDestinationFolder>-tag tells wro4j, where it should put the generated CSS-file. You can adjust that to suite your needs.

+

That’s it: now the same CSS-file, which is created on the fly by the wro4j servlet-filter when using mvn jetty:run and, thus, enables dynamic reloading of our LESS-resources, is generated during the build-process by the wro4j-maven-plugin.

+

Cleanup and further considerations

+

lesscss-maven-plugin

+

If you already compile your LESS-resources with the lesscss-maven-plugin, you can stick with it and skip step 3. But I strongly recommend giving wro4j-maven-plugin a try, because it is a much more powerfull tool, that can speed up your final webapp even more.

+

Clean up your mess

+

With a configuration like the above one, your LESS-resources and wro4j-configuration-files will be packed into your production-war. That might be confusing later, because neither wro4j nor LESS is used in the final war. You can add the following to your pom.xml to exclude these files from your war for the sake of clarity:

+
  
+  <plugin>
+    <artifactId>maven-war-plugin</artifactId>
+    <configuration>
+      <warSourceExcludes>
+        WEB-INF/wro.*,
+        less/**
+      </warSourceExcludes>
+    </configuration>
+  </plugin>
+  
+          
+

What’s next?

+

We only scrached the surface, of what can be done with wro4j. Based on this configuration, you can easily enable additional features to fine-tune your final build for maximum speed. You really should take a look at the list of available Processors!

+
+ +
+ + +
+

Leave a Reply

+ +
+

Logged in as Kai Moritz. Log out »

+ +

+

+ + +

+ +

+
+
+
+ diff --git a/content/blog/2020/comments.html b/content/blog/2020/comments.html new file mode 100644 index 00000000..e150735f --- /dev/null +++ b/content/blog/2020/comments.html @@ -0,0 +1,478 @@ +--- +categories: + - hibernate + - java + - maven +date: "2020-06-15T19:15:58+00:00" +title: hibernate4-maven-plugin +url: /hibernate4-maven-plugin-a-simple-plugin-for-generating-a-database-schema-from-hibernate-4-mapping-annotations/ +--- +
+
+
+

hibernate4-maven-plugin

+ +
+
+

A simple Plugin for generating a Database-Schema from Hibernate 4 Mapping-Annotations

+

+ Hibernate comes with the buildin functionality, to automatically create or update the database schema. This functionality is configured in the session-configuraton via the parameter hbm2ddl.auto (see Hibernate Reference Documentation – Chapter 3.4. Optional configuration properties). But doing so is not very wise, because you can easily corrupt or erase your production database, if this configuration parameter slips through to your production environment. +

+

+ Alternatively, you can run the tools SchemaExport or SchemaUpdate by hand. But that is not very comfortable and being used to maven you will quickly long for a plugin, that does that job automatically for you, when you fire up your test cases. +

+

In the good old times, there was the Maven Hibernate3 Plugin, that does this for you. But unfortunatly, this plugin is not compatible with Hibernate 4.x. Since there does not seem to be any successor for the Maven Hibernate3 Plugin and googeling does not help, I decided to write up this simple plugin (inspired by these two articles I found: Schema Export with Hibernate 4 and Maven and Schema generation with Hibernate 4, JPA and Maven). +

+

+ I hope, the resulting simple to use buletproof hibernate4-maven-plugin is usefull! +

+

+ Try it out now!

+
+ +
+ +

15 Responses to “hibernate4-maven-plugin”

+ +
    +
  1. +
    +
    + Jukes says: +
    + +

    + Hi thanks a lot for making this plugin available, great work!!
    + I have a problem generating postgres schema. Looks like the plugin ignores the data type when adding default values and that yields a syntax error from Postgres. Or maybe I’m doing something wrong. I’m using version 1.0.3.

    +

    For example I have in java:

    +

    + @Column(name = “financialEnabled”, nullable = false, columnDefinition = “default TRUE”)
    + private boolean financialEnabled; +

    +

    + Generated SQL is:
    + financialEnabled default TRUE not null, +

    +

    As you can see the data type boolean is not translated to the SQL script. Thanks a lot for your help.

    +
    + Reply +
    +
    +
      +
    • +
      +
      + Kai Moritz says: +
      + +

      + This plugin is only a tool to automate the generation of the SQL in your development-environment.
      + Questions on how to anotate your code correctly are better asked in a user-forum from hibernate or such.

      +

      + Nevertheless, I think I can give you a usefull hint:
      + You are overwriting the automatically generated column-definition with “default TRUE”.
      + Try it with

      +

      + @Column(name = “financialEnabled”, nullable = false)
      + private boolean financialEnabled;

      +
      + Reply +
      +
      +
    • +
    +
  2. +
  3. +
    +
    + Milios says: +
    + +

    Hi,

    +

    + looks like a very nice plugin. Unfortunately, part of our entities are in other modules/dependencies.
    + Do you plan to add the possibility to scan also for dependencies of the project or at least of the plugin?

    +

    Also, when I only want to generate the SQL and use the following configuration, I got nothing.

    +

    Config:

    +

    + de.juplo
    + hibernate4-maven-plugin
    + 1.0.2

    +

    + true
    + SCRIPT
    + NONE
    + com.deutscheboerse.hibernate.PostgreSQLDialect
    + ${project.build.directory}/hibernate4/cmm-schema.sql

    +

    + com.deutscheboerse.energy
    + energy-commons-hibernate
    + ${commons.hibernate.version}

    +

    + org.springframework.security
    + spring-security-core
    + ${spring.security.version}

    +

    + org.slf4j
    + slf4j-log4j12
    + ${slf4j.version}

    +

    + Output:
    + mvn hibernate4:export -e
    + [INFO] Error stacktraces are turned on.
    + [INFO] Scanning for projects…
    + [INFO]
    + [INFO] ————————————————————————
    + [INFO] Building CMM WAR 1.0.0-RC5-SNAPSHOT
    + [INFO] ————————————————————————
    + [INFO]
    + [INFO] — hibernate4-maven-plugin:1.0.2:export (default-cli) @ cmm-war —
    + [INFO] Scanning directory D:\_dev\work\ii\src\cmm\trunk\cmm-war\target\classes f
    + [INFO] No hibernate-properties-file found! (Checked path: D:\_dev\work\ii\src\cm
    + [INFO] Gathered hibernate-configuration (turn on debugging for details):
    + [INFO] hibernate.dialect = com.deutscheboerse.hibernate.PostgreSQLDialect
    + [INFO] HHH000400: Using dialect: com.deutscheboerse.hibernate.PostgreSQLDialect
    + [INFO] ————————————————————————
    + [INFO] BUILD SUCCESS
    + [INFO] ————————————————————————
    + [INFO] Total time: 10.932s
    + [INFO] Finished at: Thu Oct 10 12:51:05 UTC 2013
    + [INFO] Final Memory: 9M/23M
    + [INFO] ————————————————————————

    +

    + Thanks for any help,
    + Milos. +

    +
    + Reply +
    +
    +
      +
    • +
      +
      + Kai Moritz says: +
      + +

      + Yes, I am working on the possibility, to scan for annotations in dependencies.
      + Unfortunatly, I have no example-project for this use-case by hand.
      + It would help a lot, if you could provide a sample-project on github or such. +

      +

      Greetings kai

      +
      + Reply +
      +
      + +
    • +
    +
  4. +
  5. +
    +
    + Pedro says:
    + + + +

    Following my previous question, here is the debug info

    +

    [DEBUG] Dependency: /Users/pmarques/.m2/repository/org/springframework/security/spring-security-acl/3.1.4.RELEASE/spring-security-acl-3.1.4.RELEASE.jar
    + [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/atomikos-util/3.6.5/atomikos-util-3.6.5.jar
    + [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-api/3.6.5/transactions-api-3.6.5.jar
    + [DEBUG] Dependency: /Users/pmarques/.m2/repository/javax/transaction/transaction-api/1.1/transaction-api-1.1.jar
    + [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-jdbc-deprecated/3.6.5/transactions-jdbc-deprecated-3.6.5.jar
    + [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-jdbc/3.6.5/transactions-jdbc-3.6.5.jar
    + [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-jta/3.6.5/transactions-jta-3.6.5.jar
    + [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions/3.6.5/transactions-3.6.5.jar
    + [DEBUG] Dependency: /Users/pmarques/.m2/repository/org/apache/geronimo/specs/geronimo-jta_1.0.1B_spec/1.0.1/geronimo-jta_1.0.1B_spec-1.0.1.jar
    + [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-jms-deprecated/3.6.5/transactions-jms-deprecated-3.6.5.jar
    + [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-jms/3.6.5/transactions-jms-3.6.5.jar
    + [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-hibernate3/3.6.5/transactions-hibernate3-3.6.5.jar
    + [INFO] Scanning directory /target/classes for annotated classes…

    + +
    + Reply
    +
    +
  6. +
  7. +
    +
    + Pedro says:
    + + + +

    Hi,

    +

    I have the following problem.
    + The project that I use to test (and use the plugin) has the annotated classes as a dependency.
    + I am getting the error:
    + No annotated classes found in directory /target/classes

    +

    Shouldn’t the plugin scan all the dependencies also?

    +

    Thanks,
    + Pedro.

    + +
    + Reply
    +
    +
      +
    • +
      +
      + Kai Moritz says:
      + + + +

      Hi Pedro,

      +

      I think, that your observation is right.
      + But otherwise, dependencies should only be scanned if requested, because automatic scanning of the dependencies might lead to errors in other situations.

      +

      If you can make your project available to me (for example via github, or simply by mailing zipped version), I would add a configuration-parameter to enable/disable dependency-scanning and upload the refined plugin to central.

      +

      Regards,

      +

      Kai Moritz

      + +
      + Reply
      +
      + +
    • +
    +
  8. +
  9. +
    +
    + mike says:
    + + + +

    Hello,

    +

    I’m upgrading from hibernate3 to to hibernate4 and have moved from the hibernate3-maven-plugin to this version. I haven’t undertaken (and don’t want to just yet) the big job of changing my hbm mapping files to annotations.

    +

    As far as I can see this is a show stopper for using your nice plugin. Can you please confirm if this is the case and whether you are planning to add support for scanning for hbm files?

    +

    Many thanks,

    +

    Mike Cohen.

    + +
    + Reply
    +
    + +
  10. +
  11. +
    +
    + Victor says:
    + + + +

    Hey I have modified your code to support envers and generate auditing tables, if you want I can send you a patch. Thanks!

    + +
    + Reply
    +
    + +
  12. +
+ + + + +
+ +

Leave a Reply

+ + + + +
+ + +

Logged in as Kai Moritz. Log out »

+ + + + +

+ +

+ + +

+ +

+
+
+
+ diff --git a/content/blog/2021/wp2hugo.html b/content/blog/2021/wp2hugo.html new file mode 100644 index 00000000..a614c261 --- /dev/null +++ b/content/blog/2021/wp2hugo.html @@ -0,0 +1,157 @@ +--- +_edit_last: "2" +author: kai +categories: + - demos + - explained + - java + - kafka + - spring + - spring-boot +classic-editor-remember: classic-editor +date: "2021-02-05T17:59:38+00:00" +guid: http://juplo.de/?p=1201 +parent_post_id: null +post_id: "1201" +title: 'Implementing The Outbox-Pattern With Kafka - Part 0: The example' +url: /implementing-the-outbox-pattern-with-kafka-part-0-the-example/ + +--- +_This article is part of a Blog-Series_ + +Based on a [very simple example-project](/implementing-the-outbox-pattern-with-kafka-part-0-the-example/) +we will implemnt the [Outbox-Pattern](https://microservices.io/patterns/data/transactional-outbox.html) with [Kafka](https://kafka.apache.org/quickstart). + +- Part 0: The Example-Project +- [Part 1: Writing In The Outbox-Table](/implementing-the-outbox-pattern-with-kafka-part-1-the-outbox-table/ "Jump to the explanation what has to be added, to enqueue messages in an outbox for successfully written transactions") + +## TL;DR + +In this part, a small example-project is introduced, that features a component, which has to inform another component upon every succsessfully completed operation. + +## The Plan + +In this mini-series I will implement the [Outbox-Pattern](https://microservices.io/patterns/data/transactional-outbox.html) +as described on Chris Richardson's fabolous website [microservices.io](https://microservices.io/). + +The pattern enables you, to send a message as part of a database transaction in a reliable way, effectively turining the writing of the data +to the database and the sending of the message into an **[atomic operation](https://en.wikipedia.org/wiki/Atomicity_(database_systems))**: +either both operations are successful or neither. + +The pattern is well known and implementing it with [Kafka](https://kafka.apache.org/quickstart) looks like an easy straight forward job at first glance. +However, there are many obstacles that easily lead to an incomplete or incorrect implementation. +In this blog-series, we will circumnavigate these obstacles together step by step. + +## The Example Project + +To illustrate our implementation, we will use a simple example-project. +It mimics a part of the registration process for an web application: +a (very!) simplistic service takes registration orders for new users. + +- Successfull registration requests will return a 201 (Created), that carries the URI, under which the data of the newly registered user can be accessed in the `Location`-header: + +`echo peter | http :8080/users + HTTP/1.1 201 + Content-Length: 0 + Date: Fri, 05 Feb 2021 14:44:51 GMT + Location: http://localhost:8080/users/peter + ` +- Requests to registrate an already existing user will result in a 400 (Bad Request): + +`echo peter | http :8080/users + HTTP/1.1 400 + Connection: close + Content-Length: 0 + Date: Fri, 05 Feb 2021 14:44:53 GMT + ` +- Successfully registrated users can be listed: + `http :8080/users + HTTP/1.1 200 + Content-Type: application/json;charset=UTF-8 + Date: Fri, 05 Feb 2021 14:53:59 GMT + Transfer-Encoding: chunked + [ + { + "created": "2021-02-05T10:38:32.301", + "loggedIn": false, + "username": "peter" + }, + ... + ] + ` + +## The Messaging Use-Case + +As our messaging use-case imagine, that there has to happen several processes after a successful registration of a new user. +This may be the generation of an invoice, some business analytics or any other lengthy process that is best carried out asynchronously. +Hence, we have to generate an event, that informs the responsible services about new registrations. + +Obviously, these events should only be generated, if the registration is completed successfully. +The event must not be fired, if the registration is rejected, because a duplicate username. + +On the other hand, the publication of the event must happen reliably, because otherwise, the new might not be charged for the services, we offer... + +## The Transaction + +The users are stored in a database and the creation of a new user happens in a transaction. +A "brilliant" colleague came up with the idea, to trigger an `IncorrectResultSizeDataAccessException` to detect duplicate usernames: + +`User user = new User(username); +repository.save(user); +// Triggers an Exception, if more than one entry is found +repository.findByUsername(username); +` + +The query for the user by its names triggers an `IncorrectResultSizeDataAccessException`, if more than one entry is found. +The uncaught exception will mark the transaction for rollback, hence, canceling the requested registration. +The 400-response is then generated by a corresponding `ExceptionHandler`: + +`@ExceptionHandler +public ResponseEntity incorrectResultSizeDataAccessException( + IncorrectResultSizeDataAccessException e) +{ + LOG.info("User already exists!"); + return ResponseEntity.badRequest().build(); +} +` + +Please do not code this at home... + +But his weired implementation perfectly illustrates the requirements for our messaging use-case: +The user is written into the database. +But the registration is not successfully completed until the transaction is commited. +If the transaction is rolled back, no message must be send, because no new user was registered. + +## Decoupling with Springs EventPublisher + +In the example implementation I am using an `EventPublisher` to decouple the business logic from the implementation of the messaging. +The controller publishes an event, when a new user is registered: + +`publisher.publishEvent(new UserEvent(this, usernam)); +` + +A listener annotated with `@TransactionalEventListener` receives the events and handles the messaging: + +`@TransactionalEventListener +public void onUserEvent(UserEvent event) +{ + // Sending the message happens here... +} +` + +In non-critical use-cases, it might be sufficient to actually send the message to Kafka right here. +Spring ensures, that the message of the listener is only called, if the transaction completes successfully. +But in the case of a failure this naive implementation can loose messages. +If the application crashes, after the transaction has completed, but before the message could be send, the event would be lost. + +In the following blog posts, we will step by step implement a solution based on the Outbox-Pattern, that can guarantee Exactly-Once semantics for the send messages. + +## May The Source Be With You! + +The complete source code of the example-project can be cloned here: + +- `git clone /git/demos/spring/data-jdbc` +- `git clone https://github.com/juplo/demos-spring-data-jdbc.git` + +It includes a [Setup for Docker Compose](https://github.com/juplo/demos-spring-data-jdbc/blob/master/docker-compose.yml), that can be run without compiling +the project. And a runnable [README.sh](https://github.com/juplo/demos-spring-data-jdbc/blob/master/README.sh), that compiles and run the application and illustrates the example. diff --git a/content/blog/article.html b/content/blog/article.html deleted file mode 100644 index 050c2d01..00000000 --- a/content/blog/article.html +++ /dev/null @@ -1,302 +0,0 @@ ---- -categories: - - jetty - - less - - maven - - wro4j -date: "2013-12-06T10:58:17+00:00" -title: Combining jetty-maven-plugin and wro4j-maven-plugin for Dynamic Reloading of LESS-Resources -url: /combining-jetty-maven-plugin-and-wro4j-maven-plugin-for-dynamic-reloading-of-less-resources/ ---- -
-
-
-

Combining jetty-maven-plugin and wro4j-maven-plugin for Dynamic Reloading of LESS-Resources

- -
-
-

Ever searched for a simple configuration, that lets you use your jetty-maven-plugin as you are used to, while working with LESS to simplify your stylesheets?

-

You cannot do both, use the Client-side mode of LESS to ease development and use the lesscss-maven-plugin to automatically compile the LESS-sources into CSS for production. That does not work, because your stylesheets must be linked in different ways if you are switching between the client-side mode – which is best for development – and the pre-compiled mode – which is best for production. For the client-side mode you need something like:

-
  
-  <link rel="stylesheet" type="text/css" href="styles.css" />
-  <script src="less.js" type="text/javascript"></script>
-  
-          
-

While, for the pre-compiled mode, you want to link to your stylesheets as usual, with:

-
  
-  <link rel="stylesheet" type="text/css" href="styles.css" />
-  
-          
-

While looking for a solution to this dilemma, I stumbled accross wro4j. Originally intended, to speed up page-delivery by combining and minimizing multiple resources into one through the use of a servlet-filter, this tool also comes with a maven-plugin, that let you do the same offline, while compiling your webapp.

-

The idea is, to use the wro4j-maven-plugin to compile and combine your LESS-sources into CSS for production and to use the wro4j filter, to dynamically deliver the compiled CSS while developing. This way, you do not have to alter your HTML-code, when switching between development and production, because you always link to the CSS-files.

-

So, lets get dirty!

-

Step 1: Configure wro4j

-

First, we configure wro4j, like as we want to use it to speed up our page. The details are explained and linked on wro4j’s Getting-Started-Page. In short, we just need two files: wro.xml and wro.properties.

-

wro.xml

-

wro.xml tells wro4j, which resources should be combined and how the result should be named. I am using the following configuration to generate all LESS-Sources beneath base/ into one CSS-file called base.css:

-
  
-  <groups xmlns="http://www.isdc.ro/wro">
-    <group name="base">
-      <css>/css/base/*.css</css>
-    </group>
-  
-          
-

wro4j looks for /css/base/*.css inside the root of the web-context, which is equal to src/main/webapp in a normal maven-project. There are other ways to specifie the resources, which enable you to store them elswhere. But this approach works best for our goal, because the path is understandable for both: the wro4j servlet-filter, we are configuring now for our development-environment, and the wro4j-maven-plugin, that we will configure later for build-time compilation.

-

wro.properties

-

wro.properties in short tells wro4j, how or if it should convert the combined sources and how it should behave. I am using the following configuration to tell wro4j, that it should convert *.css-sources into CSS and do that on every request:

-
  
-  preProcessors=less4j
-  disableCache=true
-  
-          
-

You can do a lot more here. There are countless configuration options to fine-tune the behaviour of wro4j. The disableCache=true is crucial, because we would not see the changes take effect when developing with jetty-maven-plugin later on. You can also do much more with your resources here, for example minimizing. But for our goal, we are now only intrested in the compilation of our LESS-sources.

-

Step 2: Configure the wro4j servlet-filter

-

Configuring the filter in the web.xml is easy. It is explained in wro4j’s installation-insctuctions. But the trick is, that we do not want to configure that filter for the production-version of our webapp, because we want to compile the resources offline, when the webapp is build. To acchieve this, we can use the <overrideDescriptor>-Parameter of the jetty-maven-plugin.

-

<overrideDescriptor>

-

This parameter lets you specify additional configuration options for the web.xml of your webapp. I am using the following configuration for my jetty-maven-plugin:

-
  
-  <plugin>
-    <groupId>org.eclipse.jetty</groupId>
-    <artifactId>jetty-maven-plugin</artifactId>
-    <configuration>
-      <webApp>
-        <overrideDescriptor>${project.basedir}/src/test/resources/jetty-web.xml</overrideDescriptor>
-      </webApp>
-    </configuration>
-    <dependencies>
-      <dependency>
-        <groupId>ro.isdc.wro4j</groupId>
-        <artifactId>wro4j-core</artifactId>
-        <version>${wro4j.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>ro.isdc.wro4j</groupId>
-        <artifactId>wro4j-extensions</artifactId>
-        <version>${wro4j.version}</version>
-        <exclusions>
-          <exclusion>
-              <groupId>javax.servlet</groupId>
-              <artifactId>servlet-api</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>org.apache.commons</groupId>
-              <artifactId>commons-lang3</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>commons-io</groupId>
-              <artifactId>commons-io</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>commons-pool</groupId>
-              <artifactId>commons-pool</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>org.springframework</groupId>
-              <artifactId>spring-web</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>com.google.code.gson</groupId>
-              <artifactId>gson</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>com.google.javascript</groupId>
-              <artifactId>closure-compiler</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>com.github.lltyk</groupId>
-              <artifactId>dojo-shrinksafe</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>org.jruby</groupId>
-              <artifactId>jruby-core</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>org.jruby</groupId>
-            <artifactId>jruby-stdlib</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>org.jruby</groupId>
-              <artifactId>jruby-stdlib</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>me.n4u.sass</groupId>
-              <artifactId>sass-gems</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>nz.co.edmi</groupId>
-              <artifactId>bourbon-gem-jar</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>org.codehaus.gmaven.runtime</groupId>
-              <artifactId>gmaven-runtime-1.7</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>org.webjars</groupId>
-              <artifactId>jshint</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>org.webjars</groupId>
-              <artifactId>less</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>org.webjars</groupId>
-              <artifactId>emberjs</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>org.webjars</groupId>
-              <artifactId>handlebars</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>org.webjars</groupId>
-              <artifactId>coffee-script</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>org.webjars</groupId>
-              <artifactId>jslint</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>org.webjars</groupId>
-              <artifactId>json2</artifactId>
-          </exclusion>
-          <exclusion>
-              <groupId>org.webjars</groupId>
-              <artifactId>jquery</artifactId>
-          </exclusion>
-        </exclusions>
-      </dependency>
-    </dependencies>
-  </plugin>
-  
-          
-

The dependencies to wro4j-core and wro4j-extensions are needed by jetty, to be able to enable the filter defined below. Unfortunatly, one of the transitive dependencies of wro4j-extensions triggers an uggly error when running the jetty-maven-plugin. Therefore, all unneeded dependencies of wro4j-extensions are excluded, as a workaround for this error/bug.

-

jetty-web.xml

-

And my jetty-web.xml looks like this:

-
  
-  <?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_2_5.xsd"
-    version="2.5">
-    <filter>
-      <filter-name>wro</filter-name>
-      <filter-class>ro.isdc.wro.http.WroFilter</filter-class>
-    </filter>
-    <filter-mapping>
-      <filter-name>wro</filter-name>
-      <url-pattern>*.css</url-pattern>
-    </filter-mapping>
-  </web-app>
-  
-          
-

The filter processes any URI’s that end with .css. This way, the wro4j servlet-filter makes base.css available under any path, because for exampl /base.css, /css/base.css and /foo/bar/base.css all end with .css.

-

This is all, that is needed to develop with dynamically reloadable compiled LESS-resources. Just fire up your browser and browse to /what/you/like/base.css. (But do not forget to put some LESS-files in src/main/webapp/css/base/ first!)

-

Step 3: Install wro4j-maven-plugin

-

All that is left over to configure now, is the build-process. If you would build and deploy your webapp now, the CSS-file base.css would not be generated and the link to your stylesheet, that already works in our jetty-maven-plugin environment would point to a 404. Hence, we need to set up the wro4j-maven-plugin. I am using this configuration:

-
  
-  <plugin>
-    <groupId>ro.isdc.wro4j</groupId>
-    <artifactId>wro4j-maven-plugin</artifactId>
-    <version>${wro4j.version}</version>
-    <configuration>
-      <wroManagerFactory>ro.isdc.wro.maven.plugin.manager.factory.ConfigurableWroManagerFactory</wroManagerFactory>
-      <cssDestinationFolder>${project.build.directory}/${project.build.finalName}/css/</cssDestinationFolder>
-    </configuration>
-    <executions>
-      <execution>
-        <phase>package</phase>
-        <goals>
-          <goal>run</goal>
-        </goals>
-      </execution>
-    </executions>
-  </plugin>
-  
-          
-

I connected the run-goal with the package-phase, because the statically compiled CSS-file is needed only in the final war. The ConfigurableWroManagerFactory tells wro4j, that it should look up further configuration options in our wro.properties-file, where we tell wro4j, that it should compile our LESS-resources. The <cssDestinationFolder>-tag tells wro4j, where it should put the generated CSS-file. You can adjust that to suite your needs.

-

That’s it: now the same CSS-file, which is created on the fly by the wro4j servlet-filter when using mvn jetty:run and, thus, enables dynamic reloading of our LESS-resources, is generated during the build-process by the wro4j-maven-plugin.

-

Cleanup and further considerations

-

lesscss-maven-plugin

-

If you already compile your LESS-resources with the lesscss-maven-plugin, you can stick with it and skip step 3. But I strongly recommend giving wro4j-maven-plugin a try, because it is a much more powerfull tool, that can speed up your final webapp even more.

-

Clean up your mess

-

With a configuration like the above one, your LESS-resources and wro4j-configuration-files will be packed into your production-war. That might be confusing later, because neither wro4j nor LESS is used in the final war. You can add the following to your pom.xml to exclude these files from your war for the sake of clarity:

-
  
-  <plugin>
-    <artifactId>maven-war-plugin</artifactId>
-    <configuration>
-      <warSourceExcludes>
-        WEB-INF/wro.*,
-        less/**
-      </warSourceExcludes>
-    </configuration>
-  </plugin>
-  
-          
-

What’s next?

-

We only scrached the surface, of what can be done with wro4j. Based on this configuration, you can easily enable additional features to fine-tune your final build for maximum speed. You really should take a look at the list of available Processors!

-
- -
- - -
-

Leave a Reply

- -
-

Logged in as Kai Moritz. Log out »

- -

-

- - -

- -

-
-
-
- diff --git a/content/blog/comments.html b/content/blog/comments.html deleted file mode 100644 index e150735f..00000000 --- a/content/blog/comments.html +++ /dev/null @@ -1,478 +0,0 @@ ---- -categories: - - hibernate - - java - - maven -date: "2020-06-15T19:15:58+00:00" -title: hibernate4-maven-plugin -url: /hibernate4-maven-plugin-a-simple-plugin-for-generating-a-database-schema-from-hibernate-4-mapping-annotations/ ---- -
-
-
-

hibernate4-maven-plugin

- -
-
-

A simple Plugin for generating a Database-Schema from Hibernate 4 Mapping-Annotations

-

- Hibernate comes with the buildin functionality, to automatically create or update the database schema. This functionality is configured in the session-configuraton via the parameter hbm2ddl.auto (see Hibernate Reference Documentation – Chapter 3.4. Optional configuration properties). But doing so is not very wise, because you can easily corrupt or erase your production database, if this configuration parameter slips through to your production environment. -

-

- Alternatively, you can run the tools SchemaExport or SchemaUpdate by hand. But that is not very comfortable and being used to maven you will quickly long for a plugin, that does that job automatically for you, when you fire up your test cases. -

-

In the good old times, there was the Maven Hibernate3 Plugin, that does this for you. But unfortunatly, this plugin is not compatible with Hibernate 4.x. Since there does not seem to be any successor for the Maven Hibernate3 Plugin and googeling does not help, I decided to write up this simple plugin (inspired by these two articles I found: Schema Export with Hibernate 4 and Maven and Schema generation with Hibernate 4, JPA and Maven). -

-

- I hope, the resulting simple to use buletproof hibernate4-maven-plugin is usefull! -

-

- Try it out now!

-
- -
- -

15 Responses to “hibernate4-maven-plugin”

- -
    -
  1. -
    -
    - Jukes says: -
    - -

    - Hi thanks a lot for making this plugin available, great work!!
    - I have a problem generating postgres schema. Looks like the plugin ignores the data type when adding default values and that yields a syntax error from Postgres. Or maybe I’m doing something wrong. I’m using version 1.0.3.

    -

    For example I have in java:

    -

    - @Column(name = “financialEnabled”, nullable = false, columnDefinition = “default TRUE”)
    - private boolean financialEnabled; -

    -

    - Generated SQL is:
    - financialEnabled default TRUE not null, -

    -

    As you can see the data type boolean is not translated to the SQL script. Thanks a lot for your help.

    -
    - Reply -
    -
    -
      -
    • -
      -
      - Kai Moritz says: -
      - -

      - This plugin is only a tool to automate the generation of the SQL in your development-environment.
      - Questions on how to anotate your code correctly are better asked in a user-forum from hibernate or such.

      -

      - Nevertheless, I think I can give you a usefull hint:
      - You are overwriting the automatically generated column-definition with “default TRUE”.
      - Try it with

      -

      - @Column(name = “financialEnabled”, nullable = false)
      - private boolean financialEnabled;

      -
      - Reply -
      -
      -
    • -
    -
  2. -
  3. -
    -
    - Milios says: -
    - -

    Hi,

    -

    - looks like a very nice plugin. Unfortunately, part of our entities are in other modules/dependencies.
    - Do you plan to add the possibility to scan also for dependencies of the project or at least of the plugin?

    -

    Also, when I only want to generate the SQL and use the following configuration, I got nothing.

    -

    Config:

    -

    - de.juplo
    - hibernate4-maven-plugin
    - 1.0.2

    -

    - true
    - SCRIPT
    - NONE
    - com.deutscheboerse.hibernate.PostgreSQLDialect
    - ${project.build.directory}/hibernate4/cmm-schema.sql

    -

    - com.deutscheboerse.energy
    - energy-commons-hibernate
    - ${commons.hibernate.version}

    -

    - org.springframework.security
    - spring-security-core
    - ${spring.security.version}

    -

    - org.slf4j
    - slf4j-log4j12
    - ${slf4j.version}

    -

    - Output:
    - mvn hibernate4:export -e
    - [INFO] Error stacktraces are turned on.
    - [INFO] Scanning for projects…
    - [INFO]
    - [INFO] ————————————————————————
    - [INFO] Building CMM WAR 1.0.0-RC5-SNAPSHOT
    - [INFO] ————————————————————————
    - [INFO]
    - [INFO] — hibernate4-maven-plugin:1.0.2:export (default-cli) @ cmm-war —
    - [INFO] Scanning directory D:\_dev\work\ii\src\cmm\trunk\cmm-war\target\classes f
    - [INFO] No hibernate-properties-file found! (Checked path: D:\_dev\work\ii\src\cm
    - [INFO] Gathered hibernate-configuration (turn on debugging for details):
    - [INFO] hibernate.dialect = com.deutscheboerse.hibernate.PostgreSQLDialect
    - [INFO] HHH000400: Using dialect: com.deutscheboerse.hibernate.PostgreSQLDialect
    - [INFO] ————————————————————————
    - [INFO] BUILD SUCCESS
    - [INFO] ————————————————————————
    - [INFO] Total time: 10.932s
    - [INFO] Finished at: Thu Oct 10 12:51:05 UTC 2013
    - [INFO] Final Memory: 9M/23M
    - [INFO] ————————————————————————

    -

    - Thanks for any help,
    - Milos. -

    -
    - Reply -
    -
    -
      -
    • -
      -
      - Kai Moritz says: -
      - -

      - Yes, I am working on the possibility, to scan for annotations in dependencies.
      - Unfortunatly, I have no example-project for this use-case by hand.
      - It would help a lot, if you could provide a sample-project on github or such. -

      -

      Greetings kai

      -
      - Reply -
      -
      - -
    • -
    -
  4. -
  5. -
    -
    - Pedro says:
    - - - -

    Following my previous question, here is the debug info

    -

    [DEBUG] Dependency: /Users/pmarques/.m2/repository/org/springframework/security/spring-security-acl/3.1.4.RELEASE/spring-security-acl-3.1.4.RELEASE.jar
    - [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/atomikos-util/3.6.5/atomikos-util-3.6.5.jar
    - [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-api/3.6.5/transactions-api-3.6.5.jar
    - [DEBUG] Dependency: /Users/pmarques/.m2/repository/javax/transaction/transaction-api/1.1/transaction-api-1.1.jar
    - [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-jdbc-deprecated/3.6.5/transactions-jdbc-deprecated-3.6.5.jar
    - [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-jdbc/3.6.5/transactions-jdbc-3.6.5.jar
    - [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-jta/3.6.5/transactions-jta-3.6.5.jar
    - [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions/3.6.5/transactions-3.6.5.jar
    - [DEBUG] Dependency: /Users/pmarques/.m2/repository/org/apache/geronimo/specs/geronimo-jta_1.0.1B_spec/1.0.1/geronimo-jta_1.0.1B_spec-1.0.1.jar
    - [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-jms-deprecated/3.6.5/transactions-jms-deprecated-3.6.5.jar
    - [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-jms/3.6.5/transactions-jms-3.6.5.jar
    - [DEBUG] Dependency: /Users/pmarques/.m2/repository/com/atomikos/transactions-hibernate3/3.6.5/transactions-hibernate3-3.6.5.jar
    - [INFO] Scanning directory /target/classes for annotated classes…

    - -
    - Reply
    -
    -
  6. -
  7. -
    -
    - Pedro says:
    - - - -

    Hi,

    -

    I have the following problem.
    - The project that I use to test (and use the plugin) has the annotated classes as a dependency.
    - I am getting the error:
    - No annotated classes found in directory /target/classes

    -

    Shouldn’t the plugin scan all the dependencies also?

    -

    Thanks,
    - Pedro.

    - -
    - Reply
    -
    -
      -
    • -
      -
      - Kai Moritz says:
      - - - -

      Hi Pedro,

      -

      I think, that your observation is right.
      - But otherwise, dependencies should only be scanned if requested, because automatic scanning of the dependencies might lead to errors in other situations.

      -

      If you can make your project available to me (for example via github, or simply by mailing zipped version), I would add a configuration-parameter to enable/disable dependency-scanning and upload the refined plugin to central.

      -

      Regards,

      -

      Kai Moritz

      - -
      - Reply
      -
      - -
    • -
    -
  8. -
  9. -
    -
    - mike says:
    - - - -

    Hello,

    -

    I’m upgrading from hibernate3 to to hibernate4 and have moved from the hibernate3-maven-plugin to this version. I haven’t undertaken (and don’t want to just yet) the big job of changing my hbm mapping files to annotations.

    -

    As far as I can see this is a show stopper for using your nice plugin. Can you please confirm if this is the case and whether you are planning to add support for scanning for hbm files?

    -

    Many thanks,

    -

    Mike Cohen.

    - -
    - Reply
    -
    - -
  10. -
  11. -
    -
    - Victor says:
    - - - -

    Hey I have modified your code to support envers and generate auditing tables, if you want I can send you a patch. Thanks!

    - -
    - Reply
    -
    - -
  12. -
- - - - -
- -

Leave a Reply

- - - - -
- - -

Logged in as Kai Moritz. Log out »

- - - - -

- -

- - -

- -

-
-
-
- diff --git a/content/blog/wp2hugo.html b/content/blog/wp2hugo.html deleted file mode 100644 index a614c261..00000000 --- a/content/blog/wp2hugo.html +++ /dev/null @@ -1,157 +0,0 @@ ---- -_edit_last: "2" -author: kai -categories: - - demos - - explained - - java - - kafka - - spring - - spring-boot -classic-editor-remember: classic-editor -date: "2021-02-05T17:59:38+00:00" -guid: http://juplo.de/?p=1201 -parent_post_id: null -post_id: "1201" -title: 'Implementing The Outbox-Pattern With Kafka - Part 0: The example' -url: /implementing-the-outbox-pattern-with-kafka-part-0-the-example/ - ---- -_This article is part of a Blog-Series_ - -Based on a [very simple example-project](/implementing-the-outbox-pattern-with-kafka-part-0-the-example/) -we will implemnt the [Outbox-Pattern](https://microservices.io/patterns/data/transactional-outbox.html) with [Kafka](https://kafka.apache.org/quickstart). - -- Part 0: The Example-Project -- [Part 1: Writing In The Outbox-Table](/implementing-the-outbox-pattern-with-kafka-part-1-the-outbox-table/ "Jump to the explanation what has to be added, to enqueue messages in an outbox for successfully written transactions") - -## TL;DR - -In this part, a small example-project is introduced, that features a component, which has to inform another component upon every succsessfully completed operation. - -## The Plan - -In this mini-series I will implement the [Outbox-Pattern](https://microservices.io/patterns/data/transactional-outbox.html) -as described on Chris Richardson's fabolous website [microservices.io](https://microservices.io/). - -The pattern enables you, to send a message as part of a database transaction in a reliable way, effectively turining the writing of the data -to the database and the sending of the message into an **[atomic operation](https://en.wikipedia.org/wiki/Atomicity_(database_systems))**: -either both operations are successful or neither. - -The pattern is well known and implementing it with [Kafka](https://kafka.apache.org/quickstart) looks like an easy straight forward job at first glance. -However, there are many obstacles that easily lead to an incomplete or incorrect implementation. -In this blog-series, we will circumnavigate these obstacles together step by step. - -## The Example Project - -To illustrate our implementation, we will use a simple example-project. -It mimics a part of the registration process for an web application: -a (very!) simplistic service takes registration orders for new users. - -- Successfull registration requests will return a 201 (Created), that carries the URI, under which the data of the newly registered user can be accessed in the `Location`-header: - -`echo peter | http :8080/users - HTTP/1.1 201 - Content-Length: 0 - Date: Fri, 05 Feb 2021 14:44:51 GMT - Location: http://localhost:8080/users/peter - ` -- Requests to registrate an already existing user will result in a 400 (Bad Request): - -`echo peter | http :8080/users - HTTP/1.1 400 - Connection: close - Content-Length: 0 - Date: Fri, 05 Feb 2021 14:44:53 GMT - ` -- Successfully registrated users can be listed: - `http :8080/users - HTTP/1.1 200 - Content-Type: application/json;charset=UTF-8 - Date: Fri, 05 Feb 2021 14:53:59 GMT - Transfer-Encoding: chunked - [ - { - "created": "2021-02-05T10:38:32.301", - "loggedIn": false, - "username": "peter" - }, - ... - ] - ` - -## The Messaging Use-Case - -As our messaging use-case imagine, that there has to happen several processes after a successful registration of a new user. -This may be the generation of an invoice, some business analytics or any other lengthy process that is best carried out asynchronously. -Hence, we have to generate an event, that informs the responsible services about new registrations. - -Obviously, these events should only be generated, if the registration is completed successfully. -The event must not be fired, if the registration is rejected, because a duplicate username. - -On the other hand, the publication of the event must happen reliably, because otherwise, the new might not be charged for the services, we offer... - -## The Transaction - -The users are stored in a database and the creation of a new user happens in a transaction. -A "brilliant" colleague came up with the idea, to trigger an `IncorrectResultSizeDataAccessException` to detect duplicate usernames: - -`User user = new User(username); -repository.save(user); -// Triggers an Exception, if more than one entry is found -repository.findByUsername(username); -` - -The query for the user by its names triggers an `IncorrectResultSizeDataAccessException`, if more than one entry is found. -The uncaught exception will mark the transaction for rollback, hence, canceling the requested registration. -The 400-response is then generated by a corresponding `ExceptionHandler`: - -`@ExceptionHandler -public ResponseEntity incorrectResultSizeDataAccessException( - IncorrectResultSizeDataAccessException e) -{ - LOG.info("User already exists!"); - return ResponseEntity.badRequest().build(); -} -` - -Please do not code this at home... - -But his weired implementation perfectly illustrates the requirements for our messaging use-case: -The user is written into the database. -But the registration is not successfully completed until the transaction is commited. -If the transaction is rolled back, no message must be send, because no new user was registered. - -## Decoupling with Springs EventPublisher - -In the example implementation I am using an `EventPublisher` to decouple the business logic from the implementation of the messaging. -The controller publishes an event, when a new user is registered: - -`publisher.publishEvent(new UserEvent(this, usernam)); -` - -A listener annotated with `@TransactionalEventListener` receives the events and handles the messaging: - -`@TransactionalEventListener -public void onUserEvent(UserEvent event) -{ - // Sending the message happens here... -} -` - -In non-critical use-cases, it might be sufficient to actually send the message to Kafka right here. -Spring ensures, that the message of the listener is only called, if the transaction completes successfully. -But in the case of a failure this naive implementation can loose messages. -If the application crashes, after the transaction has completed, but before the message could be send, the event would be lost. - -In the following blog posts, we will step by step implement a solution based on the Outbox-Pattern, that can guarantee Exactly-Once semantics for the send messages. - -## May The Source Be With You! - -The complete source code of the example-project can be cloned here: - -- `git clone /git/demos/spring/data-jdbc` -- `git clone https://github.com/juplo/demos-spring-data-jdbc.git` - -It includes a [Setup for Docker Compose](https://github.com/juplo/demos-spring-data-jdbc/blob/master/docker-compose.yml), that can be run without compiling -the project. And a runnable [README.sh](https://github.com/juplo/demos-spring-data-jdbc/blob/master/README.sh), that compiles and run the application and illustrates the example. diff --git a/layouts/_partials/menu/tree.html b/layouts/_partials/menu/tree.html new file mode 100644 index 00000000..a8d39bd1 --- /dev/null +++ b/layouts/_partials/menu/tree.html @@ -0,0 +1,77 @@ +{{- $page := .page }} +{{- $menuID := .menuID }} + + diff --git a/layouts/blog/year.html b/layouts/blog/year.html new file mode 100644 index 00000000..f0eb00da --- /dev/null +++ b/layouts/blog/year.html @@ -0,0 +1,105 @@ +{{- define "title" }} +

+ {{ .Title }} + {{- if (.Param "ShowRssButtonInSectionTermList") }} + {{- $rss := (.OutputFormats.Get "rss") }} + {{- if (eq .Kind `page`) }} + {{- $rss = (.Parent.OutputFormats.Get "rss") }} + {{- end }} + {{- with $rss }} + + + + + + + + {{- end }} + {{- end }} +

+ {{- if .Description }} +
+ {{ .Description }} +
+ {{- end }} +{{- end }}{{/* end title */}} + +{{- define "main" }} +{{- range .Pages.GroupByPublishDate "2006" }} +{{- if ne .Key "0001" }} +
+ {{- $year := replace .Key "0001" "" }} +

+ + {{- $year -}} + +

+ {{- range .Pages.GroupByDate "January" }} +
+
+ {{- range .Pages }} + {{- if eq .Kind "page" }} +
+

+ {{- .Title | markdownify }} + {{- if .Draft }} + + + + + + {{- end }} +

+
+ {{- partial "post_meta.html" . -}} +
+
+ {{- end }} + {{- end }} +
+
+ {{- end }} +
+{{- end }} +{{- end }} +{{- end }}{{/* end main */}} + +{{- define "menu" }} +{{- $page := . }} + +{{- end }}{{/* end menu */}}