Featured post

Object-Relational Mapper - Do we need this?

This article is based on a discussion with Raphael Parree . Many thanks to him. What is an ORM? An ORM is a framework that helps to map...

Showing posts with label Hibernate. Show all posts
Showing posts with label Hibernate. Show all posts

2017-10-15

JBoss EAP 7 Dev Training (Oct 2017) - Trainer's statements and guidelines

Last week I participated to a training about JBoss EAP 7 development.
These are the trainer's statements and guidelines - as I recall and understood them, and completely out of context.

Web applications

  • Always front the JavaEE container with a fronting HTTPS web server (for example Undertow or the Apache httpd server) which should host all static files and act as a reverse proxy forwarding requests to dynamic resources to the JavaEE container.
  • Do not set up SSL on the JavaEE container. Set it up on the fronting web server.
  • Go for a JavaScript framework.
    • JavaScript VMs/engines are nowadays incredibly fast.
    • The whole world is already there.
  • Coming from a Java developer experience, use TypeScript instead of JavaScript.
  • My conclusion: With JSF, use BeanValidation (JSR 303) instead of JSF validators.
    • JSF validators depend on the component, while data validation has nothing to do with the page structure/component hierarchy.  There is no reason to couple validation of incoming data with JSF page's components.
  • There is no reason to submit to the server data that has not been validated before by JavaScript in the browser.
    • This is not how JSF works. This is a reason why we should avoid using JSF.
    • Addition by myself: Validation by JavaScript does not mean that the server can trust the incoming data.  The server should always validate incoming data.
  • JSF will eventually die, the question is when.
    • During the next 5 years?
  • Use ReactJS
    • It is backed and actively used by Facebook
    • AngularJS is backed by Google, but it is not really actively used by Google.

Web services & integration

  • Use REST
  • Use JSON Web Tokens for request authentication
  • Use Protocol Buffers for REST (instead of JSON) & JMS
  • Avoid distributed transactions, rather use compensation instead, as in real life.
    • The concept of transaction mandates that everything inside the transaction happens at the very same instant, while it is actually not the case.
  • With REST services, use a HTTP POST if you don't know the ID of the generated resource.
  • Use Spring REST instead of JAX-RS and RestEasy.
  • Test REST services using httpie.org
  • JAX-RS creates, by default, 1 resource class instance per request.
    • This does not scale (instantiation of objects is slow, and GC time increases, which consumes too much resources).
    • Instead, implement the @Override getSingletons() operation
  • With JAX-RS, do not use class attributes to get request headers, cookie data etc. This would imply that the one-request-per-instance strategy is needed, which does not scale well.
  • Use Jackson to do JSON binding
  • With JAX-RS, prefer to return Response objects.
  • Use Akka-HTTP to implement REST services.
    • There are both a Scala and a Java API.
    • This is a non-blocking API, which thus scales well (threads are not blocked waiting).
    • This REST API has a client-side API as well
  • For security of REST services, using BASIC auth + SSL (+ JSON web tokens) is OK
    • Both Spring REST and Akka HTTP support this out of the box.
  • MOM (message oriented middleware) is the de-facto standard for inter-system communication in large organisations.
  • You should not use a big single ESB anymore
  • Use asynchronous JMS clients
  • Use Apache Camel

CDI & EJB

  • Avoid using @Producer
    • Use producers when you need to create instances of classes of libraries/frameworks which come with their own factories: the @Producer method would thus just be a facade for these specific factories
    • Your own beans are automatically instantiated by the CDI container anyway, provided they are marked with a bean-identifying annotation.
  • Do not produce primitive (int, boolean...) or String values with @Producer, rather set the values as static variables or access these values using static methods
  • Use EJBs. There is no reason to avoid EJBs in favour of CDI-only solutions (for transactionality and security, like provided by Apache DeltaSpike).
  • Apache DeltaSpike is not mainstream, and is not supported. Be cautious about using it.
  • Inject required attributes and objects directly into the constructor, instead of using setters or attribute access.
    • If a required attribute is not available, construction should fail and the object should not be usable anyway
  • There is no need to put an interface on stateless session beans or Spring beans. Stateless session beans and Spring beans needed interfaces in the past because the generation of proxies without interface was not possible. Nowadays, with javassist and cglib, this is no more the case. The architectural benefit of putting an interface on a stateless session bean or a Spring bean has never really been used anyway.
  • You mostly want to use @Singleton beans.
    • By default, access to any method of a singleton bean is write-locked.  There is one write lock per bean instance. As there is only one singleton bean instance, there is one single write lock for all method calls, which means that methods are called sequentially, one at a time, which has a dramatic impact on performance.
    • Use @Singleton with @Lock(LockType.READ) for better performance.
  • In Session Beans, any system exception is wrapped by an EJBException by the container.
  • The EJB scheduling is quite poor compared to other scheduling APIs or frameworks.  Prefer using Quartz instead of EJB scheduling.
    • Quartz is anyway the de-facto standard in Java programming world.

Load-balancing, clustering & multiple JavaEE container instances

  • To store shared transient (non persistent, like session attributes) state, use the client's browser storage instead of distributed replicated session mechanisms.
  • Use load-balancing and stateless services
    • Avoid stateful EJBs

Wildfly & JBoss EAP

  • Put custom modules directly into the module folder of the Wildfly distribution, as siblings of the module/system folder.  Do never modify anything inside the modules/system folder.
  • A JBoss modules slot specifies a version of a module.
  • Do never work or modify with the original standalone or domain folder of your JBoss EAP/Wildfly distribution. Always use a copy.
  • Deploy DB drivers as JBoss modules, then register the driver into the container by referencing the corresponding module, then define your datasources using the registered driver.

IDE

  • Use Jetbrain's IntelliJ IDEA Ultimate edition.
  • Forget Eclipse.
  • During development, always deploy exploded archives.
    • And in IntelliJ, enable JavaScript debugging.
      • This requires the installation of a Google Chrome plugin.

Testing

  • Unit tests do not relate to a method or to a class, but to a component. A component may be composed of multiple encapsulated classes.
    • The unit of test is the component.
    • What is tested is the behaviour of the component, not its internals.
    • If we test the internals of a component, like for example each class, we would end up with too many mocks and too many tests to maintain, while these would be easy to break (any implementation refactoring would imply to maintain the tests and mocks).
  • We should test our components.
  • Dependencies to other components (usually at most a few per component to test) should be mocked.
  • Read Martin Fowler's Is TDD dead article
  • Test-first is not TDD.
  • Test-first is nice in theory.  But it fails in practice. Do not apply it.
  • Use gatling.io for performance tests
  • Use Selenium +Arquillian Drone
  • Do component unit test + end-to-end tests.
    • If you cannot do end-to-end tests, then only you should do integration tests.
  • Read the testing book with a tulip on the cover
  • The trainer mentioned BDD and cucumber.io
  • Use the specs2 Scala library to implement tests

Development practices

  • Use Docker from DEV to PROD.
    • The whole world is going down that road.
  • Always favour strong typing instead of using String.
  • Read Eric Evan's Domain Driven Design book to understand what a domain model really is.
  • Do not use magic numbers (error codes or HTTP status codes, for example)
  • Use Scala instead of Java
    • Smoothly introduce Scala by first using it for unit tests, then for actual production code.
  • Use SQL. It is a decent DSL (domain specific language) for relational data access that has lived and not been replaced for decades.
  • Understand:
  • Do not used shared mutable state. It has to be managed (threads), and at a point there are just too many threads to manage: this thread management will eventually outweigh the advantage of adding a new thread.  This solution does not scale.
    • Use functional programming paradigms instead.
      • Functional programming has no side-effects, and uses immutable non-shared states. 
  • Go to functional programming: learn Scala if you come from Java development (Haskell for hard-core functional programming) 
  • Use the Functional Java library.
  • Checked exceptions are bad
    • Throwing an exception is like a GOTO to somewhere down the stack.
    • Put exceptional results into return values instead.
      • Use Optional<> or Either<> return values.
      • Don't throw the exception, put it into the return value.
    • System/unchecked exceptions (RuntimeException) is OK, they indicate that an error occurred and the system cannot continue.
  • NULL is bad
    • Cf. Tony Hoare's billion dollar mistake 
    • Use Optional<>/Maybe<> or Either<> instead.
    • Stop returning null.
    • Stop accepting null from an operation. Wrap results of operations that return null into Optional<>/Maybe<>.
    • In Java, Object is the Ur-/top-type: all classes extend Object, and similarly, null is a bottom-type: it inherits from all classes.
      • But its behaviour does not inherit from these classes: the JVM behaves as if the implementation of any operation called on a null instance throws NullPointerException. Operations that return a object may return null, in which case what you receive is not really an instance of the promised class - it is, but it does not behave like one. This is a major flaw in the design of the Java language, which is thus not quite "honest" about how an operation can behave.
  • Avoid distributed transactions.
    • They imply additional latency
    • They do not scale well.
    • For info: The XA protocol is one implementation of the two-phase commit protocol.
  • Do not force your service consumers to manage your versions.
    • Your server should manage as much as possible different versions without impacting the consumers.
    • Do not put version numbers in your URIs.
    • In case of incompatible changes and a consumer sends a deprecated request format, just return an error message/exception.
    • In the real world, there are no versions: imagine that you fill in a form for some administration.  If you provided an older version of the form that is not supported anymore, the administration will tell you to fill the newest version of the form.  Implement a similar behaviour in your services.
  • Use reactive streams (Akka streams, for example)
  • Use random generated identifiers
    • Like, for example, a UUID.

Persistence

  • Do not use JPA if performance is important.
  • Do not use JPA if you use an anemic domain model (and transaction script services).
  • JPA is an ORM, but we don't really use object orientation (and the powerful encapsulation that comes with it), thus there is no need for an ORM and all its complex magic. I wrote an article about it, with more details.
  • In Luxembourg, Clearstream and BGL use MyBatis.
  • JPMorgan switched from Hibernate to Mybatis.
  • Use Spring JDBC or MyBatis or ScalaJDBC, but not ORMs.
  • Do not use triggers or stored procedures. Remove all the ones you have.

Optimistic locking

There are usually 3 ways to implement optimistic locking:
  1. UPDATE... WHERE {all attributes have the previous value}
    1. If any fails, then it means that the object has been updated already
  2. UPDATE... WHERE {all changed attributes have the previous value} 
    1. If any fails, then it means that the object has been updated already - more efficient, but does this really work? Other fields may have been updated as well, and this strategy would not detect it.
  3.  UPDATE... WHERE VERSION=previous version
There is usually no reason to use a VERSION field, and it should be avoided.  This puts the burden on the developers to always check the value of the VERSION field, even if in some use-cases this is irrelevant.

DevOps

  • DevOps of a system is done by a single team, which is responsible for both DEV and PROD, as well as for the build and deployment.

Software architecture

  • Software architects work for the company, not for the project. In fact, many projects are define because of the architects, not because of the business.
  • Architectural policies apply between components
    • They define how components are integrated into a bigger system
  • Design policies apply to the internals of a component
    • They depend on the actual use cases and requirements for the component.
  • Evolution:
    • 20 years ago: Component Based Design (CBD)
    • 10 years ago: SOA
    • Now: microservice architecture (MSA)
      • At most one port (as in UML) per component
  • Read the book Microservices Architecture

Miscellaneous

2017-10-14

Object-Relational Mapper - Do we need this?

This article is based on a discussion with Raphael Parree. Many thanks to him.

What is an ORM?

An ORM is a framework that helps to map objects (as in object-oriented programming) into persistent relational data structures (tables in a relational database).
The Hibernate framework is an ORM framework.

Is there a use-case for ORMs?

In object oriented programming, encapsulation is key.  It hides the internals of objects, which only expose their interface.  Domain objects (these objects which represent things of the real world) are accessed using their interface, whose operations may change the internal state of the object.  In pure object oriented design, such internals are an implementation detail hidden from the object's client. The client just does not know how the object has changed internally, it just has the guarantee (provided there is no bug), that the requested change has been applied: the requested state transition of the object has been executed and the object is now in the requested state.
If this object needs to be persisted, an very widely adopted practice is to persist the object's state into a relational database.  This permits to ensure that the object is not lost (durability) as well as to remove the object from working volatile memory and thus reuse the freed memory for other purposes.
At a later stage, some process may need to access the object again.  As the state of the object has been persisted, we need to rebuild the object using this persisted state data.
We derive from the previous paragraphs the use-cases related to data persistence:
  • One needs to persistently store an object's state, possibly into a relational database.
  • One needs to retrieve this persisted state, possibly from a relational database, in order to re-build the object, with the same state.
NOTE: these are not use cases for ORMs.

About the state of an object

An object has behaviour and state.  The behaviour of an object is defined by operations that perform state transitions of the object.
What defines the state of an object? Its attributes. The object features a set of attributes whose combined values define its state. Their values also define which state transitions are allowed or not.
An object also has properties: these properties are derived from the attributes of the object, and the object's interface may have several operations that give the ability to its client to ask for the values of its properties.  Nevertheless, due to encapsulation, the object's properties (exposed, public, external) may be different from its attributes (hidden, private/protected, internal).
As the state of the object is defined by its attributes, it is sufficient to persist the values of these attributes to be able to rebuild the object later: read these attributes from the persistent store and set their values on a new instance of the same class as the original object.

A use-case for ORMs

In this whole story, the client of the object has no idea what the values of its attributes are.  The client is thus not able to know what to store.  This means that only components which know about the internals of the object are able to determine what attributes have to be persistently stored.
This is what an ORM does.  This is what Hibernate/OpenJPA/EclipseLink/TopLink, and eventually any JPA implementation do.  An ORM knows about the internal attributes of the objects that it persists into a relational data store.  The client asks the ORM to store or retrieve the object, and the ORM does it. The client does not need to know the internals of the object to execute operations provided by the ORM. In many cases, the ORM will even automatically synchronise the in-memory's object's state with the persistent data store, latest just before the end of the transaction.  This makes sense, as the client actually does not really know if and how the object's internal state has changed, and thus has no way to know whether the persisted object's state must be updated or not.
ORMs permit us to leverage object orientation, with its powerful encapsulation, when we design a domain model. This is the actual use-case for an ORM.

Do we need ORMs?

The anemic domain model

In the Java world (at least), most systems use what Martin Fowler calls an anemic domain model: domain models consist of classes that are composed of attributes which are exposed as properties, using the well-known getter and setter methods.  These objects also usually lack operations that represent its actual state transition and which encapsulate (and hide) how the state transition occurs: to change the state of an object, instead of requesting a state transition using one of the operations exposed by the object's interface, the client usually just sets the value of the object's attributes.
In this world (our world, the real world), such anemic domain objects have no more features that a structure in C programming language. In this case, one could wonder why setters and getters are needed to expose the object's attributes (which are usually private) instead of making these attributes public.  In fact, with recent versions of Hibernate, there is no justification for this.  First versions of Hibernate were not able to directly set/get the values of attributes with reflexion (and needed getter/setter methods), but this is no more the case.

Service operations as transaction scripts

As we are relying on the anemic domain model, service operations (the ones that define the boundaries of a transaction) usually consist in retrieving objects and changing their attributes by executing a series of setters of these objects.
This actually means that the service operation does de-facto know what will be persisted, and just specifies this in the object. Latest at the end of the service operation, just before the transaction is committed, the ORM framework will execute SQL INSERT/UPDATE/DELETE statements in order to persist the new values specified by the service operations using the setter methods. (This is actually why Hibernate is a framework: you don't always need to call it, it will automatically synchronise the in-memory object state with the persisted data).
Actually, here, the service operation doesn't need to rely on an ORM to persist the objects, as there is no encapsulation: there is no hidden/encapsulated attribute that the service ignores.
A completely equivalent way to implement the service is to let the service execute itself the series of SQL statements to update the object's persisted state.  This situation is fundamentally different from using an ORM, but with an equivalent outcome regarding the persisted state.

The fundamental differences between ORMs and other data access frameworks or libraries

ORMs are complex frameworks, which do many complex things under the hood in order to persist objet state and retrieve it.  It behaves like it is magic. Magic is difficult to control and to learn. ORMs are difficult to control and to learn. Do you need this in your software?
Remember your use-cases for persistence: store an object's state and retrieve it.
OK, ORMs can do this, but they are quite complex.  Another solution is to have your service operations execute SQL statements (using a Repository/DAO class for this is OK, but not really requested - this discussion is out of scope for this article). Doing this, you have full control of what happens in your software. You don't need to spend years using the ORM to finally understand how it works. There is no more magic. There is just the complexity required by your code's business.
Other impacts of using an ORM:
  • If you specify that an attribute is lazily loaded, then it will always be lazy-loaded, whatever your use-case. But actually, lazy-loading would make sense in some use-cases, while in others, it would not. With an ORM, you have to make a choice (lazy or eager loading) and then you must stick to it for all your use-cases.
  • ORMs work on an object graph: they cascade some operations (you may specify this) and they load a graph of objects, starting from the root object and then traversing the graph using SQL JOIN statements.  If you just need the root object, you'll get the whole graph, for free. Does this always make sense? Well, it depends on the specific use case.  This also brings its set of problems (n+1 selects, for example).
  • The JPA specification does not define the behaviour of the ORM if two classes are mapped on the same table: this implies that you should have one class per table, if you want guaranteed behaviour.
  • The exact generated SQL code depends on the implementation of the ORM, and there is no guarantee that the generated code does not change between versions of the same ORM: you change the version of your ORM, and suddently, your application could become very fast, or very slow, and this is out of your control.

Conclusion

As Martin Fowler documented it, we usually do not apply object orientation, and rather use an anemic domain model. Given this, we also usually implement service operations as transaction scripts.  In this case, is there still a reason to use ORMs? I am not sure of it.
There are many ways to access relational data: directly using JDBC (I wouldn't recommend this in most cases), Spring's JDBC template, MyBatis... you name it.
Usually, these tools all permit to work with different projections of the same entity, which de-facto means that you can put the data of one table into different classes (one per projection), while this is not possible with JPA implementations (at least).
These tools do work with objects, but just as a means to avoid having to work with JDBC's result set and as a means to specify SQL statement parameters using object attributes.  No magic behaviour is involved with these tools - at least nothing that impacts the client of these frameworks.
You will be in full control of the executed SQL code, and when the code is executed. You will be in full control of how the data is updated (no useless attributes updated, no object graph traversal to find modified objects/attributes - or however this is implemented) or retrieved (no useless attributes, no useless SQL JOINs...), and it will correspond to your use-case's requirements (and not to a choice you made because of another use-case).
Provided the whole world uses anemic domain models, is there still a good reason to use ORMs? Systems using domain models which leverage encapsulation justify the use of an ORM.
For other use cases, what is the added value of using ORMs?