New Article "10 Best Java Frameworks to Use in 2021"

391 views
Skip to first unread message

lofid...@gmail.com

unread,
Mar 6, 2021, 3:13:16 AM3/6/21
to GWT Users
Just finished my article "10 Best Java Frameworks to Use in 2021"

There are a lot of such article outside but this time GWT is not dead 😅

http://bit.ly/JavaFrameworksBest2021

Enjoy and have a nice weekend,
Lofi

Frank Hossfeld

unread,
Mar 6, 2021, 9:47:36 AM3/6/21
to GWT Users
Nice

Luis Fernando Planella Gonzalez

unread,
Mar 8, 2021, 7:57:53 AM3/8/21
to GWT Users
Nice article.
However, I have to argue in favor of Gradle instead of Maven.
The project I work is so huge, and we use a lot of code generation in several places.
With Maven + Eclipse, it was a pain to have everything generated, recompiled, built, regenerated, recompiled.... all the time.
Gradle is much smarter to not redo things without need, so when we switched from Maven to Gradle, the entire IDE seemed many times faster!
Of course, for small, simple projects, even if Gradle is 10x faster than Maven, say 200ms vs 2s, it is not that terrible. In our case, with Maven, it blocked everything for several seconds, even minutes, whenever we saved some files. And that was unusable for daily work.

lofid...@gmail.com

unread,
Mar 8, 2021, 8:29:20 AM3/8/21
to GWT Users
Hi Luis,

thanks for the input. Actually I wrote the article just for fun... It's somekind of parody for weekend... ;-) I see a lot such an article "Top 10 Java Frameworks...", I thought I could also do it but more for GWT popularity (== is not dead story) ;-)

Yes, sure, if Gradle works better in that situation, go for it, no doubt for that...

I hope you could laugh a bit reading that article ;-)

Cheers,
Lofi

Thomas Broyer

unread,
Mar 8, 2021, 3:25:32 PM3/8/21
to GWT Users
Indeed it's a joke, cannot be otherwise: it says you should use Hibernate in 2021! (in the conclusion, it even says you should learn it)
(I won't give my opinion on the others in the list, don't want to start a flame war 😉)

Craig Mitchell

unread,
Mar 9, 2021, 2:29:33 AM3/9/21
to GWT Users
Indeed it's a joke, cannot be otherwise: it says you should use Hibernate in 2021! (in the conclusion, it even says you should learn it)
(I won't give my opinion on the others in the list, don't want to start a flame war 😉)

Too late.  Flame war!  ;P  But seriously, what's wrong with using Hibernate as JPA provider?  Okay, yes, there is nothing to learn, it does all its magic behind the scenes, but is there something better?  Or maybe using JPA is bad, and we go back to pure SQL?  I'm curious.

Gordan Krešić

unread,
Mar 9, 2021, 3:11:06 AM3/9/21
to google-we...@googlegroups.com
On 09. 03. 2021. 08:29, Craig Mitchell wrote:
>
> Too late.  Flame war!  ;P  But seriously, what's wrong with using Hibernate
> as JPA provider?  Okay, yes, there is nothing to learn, it does all its
> magic behind the scenes, but is there something better?  Or maybe using JPA
> is bad, and we go back to pure SQL?  I'm curious.

I did try various ORMs, including some for non-relational databases (but
then it's not an ORM, but... what?) but never figured out the benefits. They
all demo well, but when I go past most basic usage, they always felt more
like an obstacle than a tool.

Only case where I would agree using ORM saves time are projects with high
number of tables compared to complexity of their usage (simple SELECTs on
hundreds or thousands of tables). But, I don't have such a project in my
portfolio.

Can you name few other benefits? Type safety? "Compile-time checks" of SQL
"queries"? I can see *some* benefits there, but hardly ones that justifies
learning another, fairly complex, DSL on top of SQL.

From time to time I found a survey with question like "Which ORM do you
use?" and there are usually low-double-digits of percentages of users who
claim to be using "raw JDBC with SQL". It gives me hope that I'm not a lone
lunatic, but still, 80+% of users must know *something*, right?

So, if we assume that someone already knows SQL (and it's an 'if', I know),
what would be the benefits of using ORM of any kind?

Bonus question: I've been looking for years for a most simplistic SQL
templating library, mainly for things like reusing WHERE clauses (i usually
end up with fairly complex ones used in multiple queries), linking '?' with
setters on PreparedStatements and things like that. I even wrote small lib
because I was tired of experimenting, but I seriously doubt that I'm the
only one with this need and would instead like to contribute to already
existing project rather than maintain my own.

-gkresic.

Michael Conrad

unread,
Mar 9, 2021, 4:30:03 AM3/9/21
to google-we...@googlegroups.com
JDBI3 is the answer to ORMS.

It's not an ORM. per-se :-)

And the Sql Object component allows strong typing in a much easier way.

You use annotations to define sql statements with parameters in interface classes. Or, optionally, sql files.


At work I ended up converting all our DB accesses, both raw and JPA over to JDBI3.



--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-web-toolkit/21b217be-c3b1-884e-8a98-4709ae383d7b%40steatoda.com.

lofid...@gmail.com

unread,
Mar 9, 2021, 4:34:18 AM3/9/21
to GWT Users
@TBroyer: of course we are going to start a flame war for Hibernate ;-)

"Hibernate" is the most searched word in Google 2021... OK, I mean "how to hibernate your PC" :-)

I agree with @Gordan, it depends on the use case. Strangely enough, we have today ORM also on Android Room (https://developer.android.com/training/data-storage/room) and iOS Core Data (https://developer.apple.com/documentation/coredata). So from the resources and speed point of view, it seems that they are just fine.

Actually it's a pitty that the standard SQLJ (https://en.wikipedia.org/wiki/SQLJ) did not get any further, I think it would be a good choice if you need SQL but need the "type and compile time" safety in Java.

Cheers,
Lofi

Raúl Pampliega Mayoral

unread,
Mar 9, 2021, 5:03:52 AM3/9/21
to GWT Users
We are using .Net in our backend with NHibernate and i must to say that using Linq To Sql is very helpful and let you have all queries strong typed. We also have  to mantain a small part of queries with ado directly due to performance.

I don't think using something like Hibernate would be bad nowadays If Java could have something like Linq to Sql (maybe something like jOOQ).

PD: God save flame wars!!! 

Thomas Broyer

unread,
Mar 9, 2021, 8:33:32 AM3/9/21
to GWT Users
Yes, JPA, not Hibernate per se.

jOOQ FTW!
(or SQLDelight; or even JDBI, or MyBatis if you prefer)

Thomas Broyer

unread,
Mar 9, 2021, 8:44:02 AM3/9/21
to GWT Users
Main issues with JPA: the entity caches, and lazy-loading which makes things work but are a PITA for performance (I've worked on a project where each and every HTTP request causes between 10 and 30 SQL queries, only to get the user's information and access rights; being so bad might very well be caused by the app architecture too, as it also has N+1 issues on some screens; but definitely JPA is to blame as well).
(also, the Criteria API is 🤢)

Vegegoku

unread,
Mar 9, 2021, 10:10:44 AM3/9/21
to GWT Users
I don't like Hibernate/JPA because of the horror and terror it gave me during my career years. Yet 
Hibernate appeared in times when we were having a hard time dealing with database and SQL in java, mapping/parsing query results, or even constructing the queries themselves and I have seen it going wildly bad.
Hibernate then came with its benefits and problems .. (maybe too many problems) but it came first .. and was adopted by so many.. and it became a large part of Java ecosystem ..so large that you hardly find a project that talks to the database and not using hibernate.. (we would like to see more of this)
I am not sure but maybe hibernate was there around 2008 (the oldest version I checked in maven central) imagine by that we had JOOQ first ..or JDBI ..or whatever suggested alternative... (I think most of them came after 2010 checking the issue trackers on Github) .. imagine we had text blocks :-) way before hibernate came along.

Now you see projects using hibernate for no reason (especially with how easy it is being promoted by spring).. from using it for simple CRUD (can be replaced by one of the suggested solutions) or for the complex queries (which should be replaced with one of the suggested solutions) I think.

BTW,  
@Thomas you didn't start a flame war it was just a flame, I got to learn few things from this conversation so why not flame the rest of the list? 

Douglas de Oliveira Mendes

unread,
Mar 9, 2021, 10:35:17 AM3/9/21
to google-we...@googlegroups.com
I wouldn't say you don't have to learn anything because it does magic. I like hibernate to keep code clean but gotta know what's going on to keep performance fine and get rid of concurrency issues, overwriting data.. 

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.

Thomas Broyer

unread,
Mar 9, 2021, 11:28:01 AM3/9/21
to GWT Users
On Tuesday, March 9, 2021 at 4:10:44 PM UTC+1 aka...@gmail.com wrote:
BTW,  
@Thomas you didn't start a flame war it was just a flame, I got to learn few things from this conversation so why not flame the rest of the list? 

Really? Let's go.

Spring: I think the thing I dislike the most about Spring is what many people like about it: it's an entire, wide, and fat, ecosystem. You can hardly use one piece of Spring without using everything else; I mean, each Spring piece builds on top of another Spring piece, so it's basically an all-or-nothing. I also fear that people doing mostly Spring won't know how to do things without it (like most big/fat framework actually). I'm a no-framework guy; I think each library should be usable on its own (good for it if it provides adapters to make it easier to use within a particular framework, I won't care), and Spring is the exact opposite.

Maven: well, Maven is so utterly broken as a scalable build tool… They're finally talking about Maven 4 bringing breaking changes to the "build POM" (as opposed to the "deployed POM" you use from repositories), but as long as they'll keep that linear lifecycle, and project model being mutable (and mutated!) during build execution, it'll be a big no-go for me. If you need to learn one build tool, let it be Gradle, not Maven.
(fwiw, I'm migrating all projects at work from Maven to Gradle; I'm being asked to migrate them, because it makes things so much more usable and enjoyable!)

Mockito: well, most of the time, you shouldn't use mocks. If you need mocks, it generally says more about the structure and testability of your code than the readability of your tests. Of all mocking tools, indeed Mockito is likely the best, but it's the kind of tools you shouldn't be reaching for to being with.

Gordan Krešić

unread,
Mar 9, 2021, 11:47:03 AM3/9/21
to google-we...@googlegroups.com
On 09. 03. 2021. 17:28, Thomas Broyer wrote:
>
> Spring: I think the thing I dislike the most about Spring is what many
> people like about it: it's an entire, wide, and fat, ecosystem. You can
> hardly use one piece of Spring without using everything else; I mean, each
> Spring piece builds on top of another Spring piece, so it's basically an
> all-or-nothing. I also fear that people doing mostly Spring won't know how
> to do things without it (like most big/fat framework actually). I'm a
> no-framework guy; I think each library should be usable on its own (good for
> it if it provides adapters to make it easier to use within a particular
> framework, I won't care), and Spring is the exact opposite.

Besides being a kitchen sink, it's also very slow. We can argue about speed
of Spring layer in an app having database and network stacks, but comparing
just that one layer with non-Spring code may result in 10x difference in
throughput (not 10%, but 10x - order of magnitude).

If anyone is interested in details, here is sample test case I put to demo
this (it was a bet :) ):

https://github.com/gkresic/muddy-waters

"Whale" is the way we are building things past few years, but Shark may be
interesting if you are considering microservices. Notice that Whale is
feature-comparable to Megalodon (Spring), yet 3-4 times faster (and provides
interchangeable libs, as you pointed out).

Relevant fact: prior to that test I had zero experience with Rapidoid and
DSL-JSON - I found them simply by googling "fast java [ (rest server) (JSON)
]". Also, I had verly limited (and outdated) experiece with Spring. Yet,
both are implemented in only few lines of code, but they differ an order of
magnitude in speed.

-gkresic.

Thomas Broyer

unread,
Mar 9, 2021, 1:55:18 PM3/9/21
to GWT Users
Using a similar approach to your "whale" for 8 years or so too.
We add to that Lightbend Config and Picocli (after having tested args4j and jcommander), and jOOQ then indeed.
Using RestEASY or GraphQL-Java depending on needs, along with Handlebars-java and/or Jackson.
But I know I can easily switch from Jetty to Tomcat or Undertow or whatever, from RestEASY to Jersey (I've actually done the reverse, because integrating with Guice was hard at the time), from Guice to Dagger or H2 or whatever, from Jackson to Moshi or GSON, etc.
And more importantly, we copy/paste/adapt a couple files that glue those things together (Jetty with RestEASY and static files serving, RestEASY and Guice, etc.) from projects to projects, rather than packaging them into a lib that would try to be generic: patterns over frameworks.

Craig Mitchell

unread,
Mar 9, 2021, 6:00:20 PM3/9/21
to GWT Users
I was ready to dislike Spingboot, because of its all encompassing nature.  But it just works, and works well.

Unlike Maven, grrr, Maven.

Most informative flame war I've been in.  Thanks all, I've learnt a lot.  :)

Craig Mitchell

unread,
Mar 9, 2021, 6:41:45 PM3/9/21
to GWT Users
Also now switching from JPA (Hibernate), to jOOQ.  As, while our DB is (currently) fairly simple, it needs to be as fast as possible.  So, thanks again!  :)

pavel....@gmail.com

unread,
Mar 10, 2021, 10:13:03 AM3/10/21
to GWT Users
We had the same problem with maven but at the end, maven's multi-module project and profiles helped to solve it.

понеділок, 8 березня 2021 р. о 13:57:53 UTC+1 Luis Fernando Planella Gonzalez пише:

Thomas Broyer

unread,
Mar 10, 2021, 10:25:47 AM3/10/21
to GWT Users


On Wednesday, March 10, 2021 at 4:13:03 PM UTC+1 pavel....@gmail.com wrote:
We had the same problem with maven but at the end, maven's multi-module project and profiles helped to solve hack around it.

There, fixed it for you 😉

(and yet, gwt-maven-archetypes use a "dev" profile 🤷, but it's know to be kind of hackish in places due to Maven and jetty-maven-plugin's limitations)

Vegegoku

unread,
Mar 10, 2021, 10:42:21 AM3/10/21
to GWT Users
On Tuesday, March 9, 2021 at 6:28:01 PM UTC+2 t.br...@gmail.com wrote:
On Tuesday, March 9, 2021 at 4:10:44 PM UTC+1 aka...@gmail.com wrote:
BTW,  
@Thomas you didn't start a flame war it was just a flame, I got to learn few things from this conversation so why not flame the rest of the list? 

Really? Let's go.

Spring: I think the thing I dislike the most about Spring is what many people like about it: it's an entire, wide, and fat, ecosystem. You can hardly use one piece of Spring without using everything else; I mean, each Spring piece builds on top of another Spring piece, so it's basically an all-or-nothing. I also fear that people doing mostly Spring won't know how to do things without it (like most big/fat framework actually).


That does really summaries it about spring, also I hate how it is being overused for simple projects,  Like sucking this huge ecosystem just because we need dependency injection or want to talk to the database (JPA -> spring data) and it ends up building a huge complexity instead of simplifying things.. (Tests for example), I once want to contribute to a project that was using spring to find out that I had to inject a single bean into 500+ other classes using the constructor where even the arguments were not arranged to make this any easier and while doing that I had to fight merge conflicts .. it is overrated and overused .. and I pretty sure that most of spring project developer relay too much on mocking to make the tests faster or avoid such dependency injection hell.
 
I'm a no-framework guy; I think each library should be usable on its own (good for it if it provides adapters to make it easier to use within a particular framework, I won't care), and Spring is the exact opposite.

Not trying to advertise here, but I want to emphasize this point, I built dominoKit this way as each lib can actually be used alone then the only one that combines them as a framework is domino-mvp, this has proven to be a good decision in terms of adoption, development, and maintenance.

 

Maven: well, Maven is so utterly broken as a scalable build tool… They're finally talking about Maven 4 bringing breaking changes to the "build POM" (as opposed to the "deployed POM" you use from repositories), but as long as they'll keep that linear lifecycle, and project model being mutable (and mutated!) during build execution, it'll be a big no-go for me. If you need to learn one build tool, let it be Gradle, not Maven.
(fwiw, I'm migrating all projects at work from Maven to Gradle; I'm being asked to migrate them, because it makes things so much more usable and enjoyable!)

I am a maven guy who really wants to learn Gradle, I used it few times for very small projects, but something is blocking me from going deep not sure how to explain it, but I always feel confused when I am trying to do anything with Gradle, everything is explained in so many different ways that I no longer understand what is the right thing to do. recently started to study how to use Gradle to simulate my maven multi-level modules. didn't make much progress. I am using your GWT maven archetype-like structure which was a huge improvement for me, and would really love to see an example of how we achieve the same results with Gradle.
 

Mockito: well, most of the time, you shouldn't use mocks. If you need mocks, it generally says more about the structure and testability of your code than the readability of your tests. Of all mocking tools, indeed Mockito is likely the best, but it's the kind of tools you shouldn't be reaching for to being with.

IMHO tests should help you improve the design of your code, Mockito is the opposite of that, Once I converted some test cases to use manually writing test doubles (spies, fakes, stubs) instead of Mockito to show the other guy how it reduced the code in the test and improves the design. Mockito makes it super easy to look away from design issues.


Vegegoku

unread,
Mar 10, 2021, 10:44:57 AM3/10/21
to GWT Users
Even if it is opinionated, please give us Gradle GWT archetype. :-)

Josselin Bardet

unread,
Mar 10, 2021, 10:47:38 AM3/10/21
to google-we...@googlegroups.com
Le mer. 10 mars 2021 à 16:42, Vegegoku <aka...@gmail.com> a écrit :


Spring: I think the thing I dislike the most about Spring is what many people like about it: it's an entire, wide, and fat, ecosystem. You can hardly use one piece of Spring without using everything else; I mean, each Spring piece builds on top of another Spring piece, so it's basically an all-or-nothing. I also fear that people doing mostly Spring won't know how to do things without it (like most big/fat framework actually).


That does really summaries it about spring, also I hate how it is being overused for simple projects,  Like sucking this huge ecosystem just because we need dependency injection or want to talk to the database (JPA -> spring data) and it ends up building a huge complexity instead of simplifying things.. (Tests for example), I once want to contribute to a project that was using spring to find out that I had to inject a single bean into 500+ other classes using the constructor where even the arguments were not arranged to make this any easier and while doing that I had to fight merge conflicts .. it is overrated and overused .. and I pretty sure that most of spring project developer relay too much on mocking to make the tests faster or avoid such dependency injection hell.
 

Spring is well tested and works well, can handle your transctions, can help you to make AOP, can make dependency injection, etc...
Spring is for me a killer feature, I can't imagine making a project, even simple, without using it.

I don't think nowadays there is a good reason to "optimize" and don't use spring

Juan Pablo Gardella

unread,
Mar 10, 2021, 10:56:20 AM3/10/21
to GWT Users
Hi Vegeoku,

Could you please elaborate on this?

IMHO tests should help you improve the design of your code, Mockito is the opposite of that, Once I converted some test cases to use manually writing test doubles (spies, fakes, stubs) instead of Mockito to show the other guy how it reduced the code in the test and improves the design. Mockito makes it super easy to look away from design issues.

Thanks,
Juan

P.S. Amazing thread.

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.

David Nouls

unread,
Mar 10, 2021, 11:10:14 AM3/10/21
to GWT Users
I have the opposite experience with Mockito.

By using mockito I am improving my designs so that they become simple to use and easy to test.

That in combination with an injection framework (using Guice/Jukito) makes it really easy to compose software and to test in isolation. 

You do have to guard against duplicating the implementation in the unit test. This often happens when people are unit testing with the goal to have 100% coverage. They start to focus on every possible branch in the implementation instead on the functional requirements of the object under test.

I try to use a real implementation if possible and only mock certain objects that would require external information (network/database and such)

I had to cleanup test code where tests were mocking every possible parameter or dependency.

Some people dare to mock a List or even a String. I only mock objects where the API is really clean and well defined and it allows me to force error situations that are difficult to simulate otherwise. If you write many when-statements you probably are doing it wrong.

Groeten,
David

Chani Liet

unread,
Mar 10, 2021, 1:29:55 PM3/10/21
to google-we...@googlegroups.com
yeap, Spring is nice, but i prefer Quarkus - https://quarkus.io/

--

Michael Conrad

unread,
Mar 10, 2021, 1:33:24 PM3/10/21
to google-we...@googlegroups.com
At work we started out with Maven and quickly discovered you couldn't do dependencies to other projects unless they shared a parent POM. Things quickly started becoming unwieldy. Discovered "loosely coupled" projects with Gradle. We haven't looked back.

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.

Vegegoku

unread,
Mar 10, 2021, 2:15:12 PM3/10/21
to GWT Users
What i mean is that mockito make it very easy to mock things, that we end up mocking everything, have we seen tests that mock every argument going into the constructor? have we seen concrete implementation being mocked without introducing an abstraction level that opens the doors for other implementations? have wee seen code that ends up with hight coupling because we actually mocked things in the tests? I mean tests are a way to design not just to verify that code is working..this might be just my opinion but here is a small example - those are no exact conversion but they are the best I could find from the old code

@ExtendWith(MockitoExtension.class)
class SubmitIssuanceCheckRequestUseCaseTest {

@Mock
private ChecksRepository checksRepository;
@Mock
private EventPublisher eventPublisher;
@Mock
private IdentityProvider identityProvider;

@InjectMocks
private SubmitIssuanceCheckRequestUseCase submitIssuanceCheckRequestUseCase;

private String currentUserName = UUID.randomUUID().toString();

@BeforeEach
void setUp() {
when(identityProvider.currentIdentity().getName()).thenReturn(currentUserName);
}

@Test
void givenNull_whenExecute_thenShouldThrowException() {
String message = assertThrows(IllegalArgumentException.class,
() -> submitIssuanceCheckRequestUseCase.execute(null))
.getMessage();
assertThat(message).isEqualTo(CHECK_CANNOT_BE_NULL);
}

@Test
void givenStockCheck_whenExecute_thenShouldUpdateCheckStatusToIssued() {
Check check = new Check();
check.setStatus(CheckStatus.STOCK);
check.setReference(UUID.randomUUID().toString());

submitIssuanceCheckRequestUseCase.execute(check);

ArgumentCaptor<Check> captor = ArgumentCaptor.forClass(Check.class);
Mockito.verify(checksRepository).update(captor.capture());
assertThat(captor.capture().getStatus()).isEqualTo(CheckStatus.ISSUED);
assertThat(captor.capture().getReference()).isEqualTo(check.getReference());
assertThat(captor.capture().getIssuanceDate()).isNotNull();
assertThat(captor.capture().getIssuedBy()).isEqualTo(currentUserName);
}

@Test
void givenStockCheck_whenExecute_thenShouldPublishCheckIssuedEvent() {
Check check = new Check();
check.setStatus(CheckStatus.STOCK);
check.setReference(UUID.randomUUID().toString());

submitIssuanceCheckRequestUseCase.execute(check);

ArgumentCaptor<CheckEventEvent<Address>> captor = ArgumentCaptor.forClass(CheckEvent.class);
verify(eventPublisher).publish(captor.capture());
assertThat(captor.getValue().getHeader().getReference()).isEqualTo(check.getReference());
assertThat(captor.getValue().getHeader().getEventType()).isEqualTo(CHECK_ISSUED);
assertThat(captor.getValue().getBody().getPayload()).isEqualTo(check);
}
}



VS 

public class PostCheckUseCaseTest {
private PostCheckUseCase postCheckUseCase;

private Check validCheck;
private Check savedCheck;
private CheckEvent<Check> publishedEvent;
private Check publishedCheck;

@Before
public void setUp() {
postCheckUseCase = new PostCheckUseCase(
check -> this.savedCheck = check,
checkEvent -> this.publishedEvent = checkEvent,
check -> this.publishedCheck = check
);
validCheck = buildValidCheck();
}

private Check buildValidCheck() {

Check check = new Check();
check.setReference("ABCDEFGHIJKLMN");
check.setPostingType(PostingType.IMMEDIATE);
check.setStatus(CheckStatus.DEPOSITED);
check.setSubmissionDate(LocalDateTime.now());
UserDecisionLog userDecisionLog = new UserDecisionLog();
userDecisionLog.setPostingDecision(PostingDecision.INITIAL);
check.setUserDecision(Arrays.asList(userDecisionLog));

return check;
}

@Test
public void givenNullCheck_whenExecute_thenShouldThrowException() {
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> postCheckUseCase.execute(null))
.withMessage("check cannot be null");
}

@Test
public void givenValidCheck_whenExecute_thenShouldUpdateStatusWithDepositedAndSubmissionDateOnRepository() {
validCheck.setStatus(null);
validCheck.setPostingType(PostingType.IMMEDIATE);
Check postedCheck = postCheckUseCase.execute(validCheck);
assertThat(postedCheck.getStatus()).isEqualTo(CheckStatus.DEPOSITED);
assertThat(postedCheck.getSubmissionDate()).isEqualToIgnoringSeconds(LocalDateTime.now());
assertThat(getLastUserDecision(postedCheck).getPostingDecision()).isEqualTo(PostingDecision.POST_IMMEDIATELY);
assertThat(savedCheck).isEqualTo(postedCheck);
}

@Test
public void givenReceivedCheck_whenExecute_thenShouldPublishEvent() {
Check postedCheck = postCheckUseCase.execute(validCheck);

assertThat(publishedEvent.getHeader().getReference()).isEqualTo(postedCheck.getReference());
assertThat(publishedEvent.getHeader().getEventType()).isEqualTo(CheckStatus.DEPOSITED.getEventType());
assertThat(publishedEvent.getBody().getPayload()).isNotNull();
assertThat(publishedEvent.getBody().getPayload()).isSameAs(postedCheck);
}

@Test
public void givenRepresentedCheck_whenExecute_thenShouldPublishEvent() {
validCheck.setStatus(CheckStatus.REPRESENTED);
Check postedCheck = postCheckUseCase.execute(validCheck);
assertThat(publishedEvent.getHeader().getReference()).isEqualTo(postedCheck.getReference());
assertThat(publishedEvent.getHeader().getEventType()).isEqualTo(CheckStatus.REPRESENTED.getEventType());
assertThat(publishedEvent.getBody().getPayload()).isNotNull();
assertThat(publishedEvent.getBody().getPayload()).isSameAs(postedCheck);
}

@Test
public void givenValidCheck_whenExecute_thenShouldSendMessageToBank() {
Check postedCheck = postCheckUseCase.execute(validCheck);
assertThat(publishedCheck).isEqualTo(postedCheck);
}

private UserDecisionLog getLastUserDecision(Check validCheck) {
return validCheck.getUserDecision().get(validCheck.getUserDecision().size() - 1);
}

I have seen tests that way far more code just doing  ArgumentCaptor  or When(..).then(...) .. etc than any actual testing code.. it could go wildly bad...
I had to write tests in both styles to convince myself.. but I believe this will remain a topic with a debate. 

Luis Fernando Planella Gonzalez

unread,
Mar 11, 2021, 9:16:42 AM3/11/21
to GWT Users
We ended up using no plugins for GWT with Gradle. Even if there are some, none of them fit well.
Luckily, GWT compiler has a nice CLI, so...
Also, we make the gwt a subproject, as we don't use GWT RPC anyway. This helps keeping gwt-dev out of any runtime classpath!!!

Below is a trimmed version (not sure it even compiles, and it is the build.gradle for a subproject) of the build.gradle file for reference, for both compilation (even with a system flag to compile only the dev module) and for running the super dev mode:

ext {
    buildWebapp = "${project(':web').buildDir}/generated/webapp"
    gwtDev = Boolean.getBoolean('gwt.development')
}

configurations {
    gwt
}
dependencies {
    gwt(project(':api')) { transitive = false }
    gwt files(project.sourceSets.main.java.srcDirs)
    gwt files(project.sourceSets.main.resources.srcDirs)
    gwt files(project(':api').sourceSets.main.java.srcDirs)
    gwt "com.google.gwt:gwt-user:$gwtVersion"
    gwt "com.google.code.gwtx:gwtx:$gwtxVersion"
    gwt "com.github.branflake2267:gwt-maps-api:$googleMapsApiVersion"
    gwt "com.google.elemental2:elemental2-webstorage:$elementalVersion"
    gwt "com.google.elemental2:elemental2-dom:$elementalVersion"
    gwt "com.google.elemental2:elemental2-promise:$elementalVersion"
    gwt "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion"
    gwt "com.google.gwt:gwt-dev:$gwtVersion"
}

task compileGwt(type: JavaExec) {
    dependsOn compileJava
    ext {
        outDir = "$buildWebapp/gwt"
    }
    group = 'Build'
    description = 'Compile the GWT source'
    inputs.files configurations.gwt
    inputs.property 'development', gwtDev
    outputs.dir outDir
    classpath = configurations.gwt
    main = 'com.google.gwt.dev.Compiler'
    args = []
    args += ['-sourceLevel', "1.$javaVersion"]
    args += ['-war', buildWebapp]
    args += ['-logLevel', 'INFO']
    args += ['-workDir', "$buildDir/tmp/gwt"]
    args += ['-XfragmentCount', '6']
    args += ['-failOnError']
    if (gwtDev) {
        args += ['-style', 'PRETTY']
        args += ['-draftCompile']
        args += ['-optimize', '0']
        args += ['-XmethodNameDisplayMode', 'ABBREVIATED']
        args += ['org.example.MyModuleDev']
    } else {
        args += ['-style', 'OBFUSCATED']
        args += ['-optimize', '9']
        args += ['-XnoclassMetadata']
        args += ['org.example.MyModule']
    }
}
task cleanGwtTemp {
    doLast {
        ant.delete(dir: "$buildWebapp/gwt")
        ant.delete(dir: "$buildDir/tmp/gwt")
    }
}
clean {
    dependsOn cleanGwtTemp
}

task gwtSuperDev(type: JavaExec) {
    dependsOn compileJava
    description = 'Run the GWT code server for Super Dev Mode'
    classpath = configurations.gwt
    main = 'com.google.gwt.dev.codeserver.CodeServer'
    args = []
    args += ['-sourceLevel', "1.$javaVersion"]
    args += ['-launcherDir', buildWebapp]
    args += ['-logLevel', 'INFO']
    args += ['-workDir', "$buildDir/tmp/gwt"]
    args += ['-precompile']
    args += ['-failOnError']
    args += ['-bindAddress', '0.0.0.0']
    args += ['org.example.MyModuleDev']
    
    doFirst {
        file("$buildDir/tmp/gwt").mkdirs()
    }
}

Luis Fernando Planella Gonzalez

unread,
Mar 11, 2021, 9:39:37 AM3/11/21
to GWT Users
We use JPA with EclipseLink. Gave us a lot better performance than Hibernate when we compared both.
The thing I like more with ORMs is that they are class-first. One creates the entity, annotates it correctly and generate the schema.
For those liking a schema-first approach, I like a lot the Querydsl project. It is not as active nowadays as it used to be, but is very nice.
And works both for plain SQL and JPA (I HATE with passion the JPA criteria queries, Querydsl is so much more readable).
It gives us typed queries and is very extensible. You can even define your own extensions as annotated static methods and it generates those as methods in the metamodel, so things like these are possible:

// Q* are the generated classes for the Querydsl metamodel
QPerson p = QPerson.person;
List<Person> admins = query
    .select(p)
    .from(p)
    .where(
        p.role.eq(Role.ADMIN),
        p.isActive()) // This would be a custom method via extension
    .orderBy(p.name.asc())
    .fetch();

Thomas Broyer

unread,
Mar 11, 2021, 2:27:52 PM3/11/21
to GWT Users
On Thursday, March 11, 2021 at 3:39:37 PM UTC+1 Luis Fernando Planella Gonzalez wrote:
We use JPA with EclipseLink. Gave us a lot better performance than Hibernate when we compared both.
The thing I like more with ORMs is that they are class-first. One creates the entity, annotates it correctly and generate the schema.

Ah yes, that's also one of those things I dislike about JPA 😊
And retrofitting JPA on an existing schema is… not easy (or leads to non-idiomatic entities). Fortunately I've only had to do that twice I think.
Many performance issues I've seen had to do with databases when doing complex queries, so in addition to not fully controlling your SQL queries, you also don't fully control the schema; or maybe more accurately you have to learn how each JPA mapping strategy translates to SQL.
Unless I'm mistaken, this also leads to putting zero or very few "check constraints" in the database (i.e. besides not null, unique constraints and referential integrity). Lately I've used exclusion constraints in Postgres (https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-EXCLUSION) to handle complex uniqueness or non-overlapping date ranges, and other check constraints for some things others would likely implement as "business rules" in the application (things like "if that enum field's value is A then this other field must be null, and otherwise then it must be non-null and positive", or simpler things like "only one of those 2 fields can be null at a time", and in some cases they must not both be null).
 
For those liking a schema-first approach, I like a lot the Querydsl project. It is not as active nowadays as it used to be, but is very nice.
And works both for plain SQL and JPA (I HATE with passion the JPA criteria queries, Querydsl is so much more readable). 

Querydsl is quite similar to jOOQ (which can generate code from JPA entities too: https://www.jooq.org/doc/3.14/manual/code-generation/codegen-jpa/), although less "integrated" with JPA: https://www.jooq.org/doc/3.14/manual/sql-execution/alternative-execution-models/using-jooq-with-jpa/
jOOQ will always do native SQL though, whereas Querydsl will use JPQL (or similar).
 
It gives us typed queries and is very extensible. You can even define your own extensions as annotated static methods and it generates those as methods in the metamodel, so things like these are possible:

This is interesting.
I've used extension methods in a Kotlin project, that alleviates the need for such a feature; but with Java indeed one would have to write isActive(p) without that.
I'm actually not sure what I prefer.

(fwiw, JPA Criteria with JPA Metamodel in JPA 2.0 also gives you typed queries; the API still is 🤢)

lofid...@gmail.com

unread,
Mar 12, 2021, 11:05:09 AM3/12/21
to GWT Users
I'm still inside the flame ;-)

For all Non-Spring-Devs: Spring Boot Native Beta is there!
Cheers,
Lofi

Oleg Ravun

unread,
Mar 12, 2021, 11:21:46 AM3/12/21
to GWT Users
No one mentioned proxy issues with Hibernate. Am I the only one who suffers from that? Basically with those proxies you never know if your code will actually work in production because Hibernate sometimes returns proxies sometimes it does not. I have even seen (though years ago) a mix of proxies and non-proxies in the same result set. Since we've started to use inheritance extensively in our persistence entities we face issues with Hibernate proxies where standard Java approach to check "instanceof" don't work. So we have to introduce special "instance of" method and don't forget to deproxy entity before casting it to a subclass. This means that Java compiler is not able to catch bugs when such special "instanceof" and deproxying is not used. Hibernate supports byte code entity enhancing as a replacement for default usage of Hibernate proxies but we are not able to configure byte-code enhancement to work properly. For example, the same query that returns single entity with several joined entities produces just one additional query without byte-code enhancement and produces  23 additional queries with byte-code enhancement. I would have never chosen Hibernate and JPA again for several reasons. Here is another one. If code changes a property of a persistence entity you have to know if it is detached or not, depending on situation if you want the change to be propagated to DB or you just updating it for a view. So I have come to conclusion that all  the classes that use Hibernate / JPA should be hidden behind some interface and not to leak its issues to the rest of application. And those interfaces should never ever return any JPA persistence entities. And all business logic should not be in those persistence entities which means these are just shallow ORM entities.

Craig Mitchell

unread,
Mar 14, 2021, 7:54:57 PM3/14/21
to GWT Users
For all Non-Spring-Devs: Spring Boot Native Beta is there!
  • JPA / Hibernate with Spring Data supported and Hibernate Reactive for Spring Data also available. Damn my analysis article is just right, Hibernate for 2021 :-)
 
I think I'm missing something.  Spring Boot Native seems to make an exe by embedding a JVM (GraalVM).  I don't understand what that has to do with JPA / Hibernate?  Wouldn't it work just as well with jOOQ and others?

Gordan Krešić

unread,
Mar 15, 2021, 4:07:41 AM3/15/21
to google-we...@googlegroups.com
On 15. 03. 2021. 00:54, Craig Mitchell wrote:
>
> I think I'm missing something.  Spring Boot Native seems to make an exe by
> embedding a JVM (GraalVM).  I don't understand what that has to do with JPA
> / Hibernate?  Wouldn't it work just as well with jOOQ and others?

GraalVM, similar to GWT, supports only subset of Java when building native
executables. Notable feature missing is, (again, same as with GWT)
reflection, which requires declarative workarounds which are PITA (if even
possible).

Lots of existing Java libs can't be compiled to GraalVM's native image.

Fun fact: GraalVM still doesn't support generating WASM images, which is a
great opportunity for J2CL which seems to have active efforts on that front
(https://github.com/google/j2cl/commits/master).

-gkresic.

Craig Mitchell

unread,
Mar 15, 2021, 7:08:25 PM3/15/21
to GWT Users
Ah, thanks.  Sounds like most projects that want a standalone executable, will still be stuck with Launch4J and similar.
Reply all
Reply to author
Forward
0 new messages