Javers and MyBatis integration help needed - mybatis

I'm having issues trying to get MyBatis and Javers (with Spring) integrated and working. I've followed instructions at http://javers.org/documentation/spring-integration/ and gotten the Aspect setup, and annotated my entity class and registered it with Javers, and the MyBatis interface correctly annotated with #Repository and #JaversAuditable on the appropriate methods, but still haven't gotten it to work, even setting breakpoints in the Javers Aspect, but nothing triggers.
I've also gone about it the other way, using MyBatis plugin interceptor, as per http://www.mybatis.org/mybatis-3/configuration.html#plugins (then used http://www.mybatis.org/spring/xref-test/org/mybatis/spring/ExecutorInterceptor.html as a basic example for commits). However while it's triggering, it's not doing what I expected and is basically just an aspect around on the commit method, which takes a boolean rather than containing which entity(ies) are being commited which would let me pass them to Javers. I suppose I could add an interceptor on the update/insert MyBatis methods, and then stored that in a ThreadLocal or similar so that when commit/rollback was called I could pass it to Javers as necessary, but that's messy.
I've got no clue where to go from here, unless someone can see something I've missed with one of those 2 methods.

So in my confusion, I realized that since MyBatis generates the concrete object for the Mapper Interfaces, Spring never seems the creation of that object, simply has the final object registered as a Bean in the context. Thus, Javers never has a chance to process the Bean as it's created in order to do any proxying or what not as necessary.
So, silly me. So I ended up creating a Spring-Data #Repository layer that mostly just passes the call through to the Mapper. Although on updates I'm doing some extra bits which the DAO shim layer (as I'm calling it) works well for.

Related

How might you manage IntegrationFlow Spring beans dynamically using a JPA database table?

I have a scenario in which I'm looking to register IntegrationFlow Spring beans based on the contents of a JPA database table.
For example, the table will look like:
#Entity
class IntegrationFlowConfig {
private long id;
private String local;
private String remote;
}
and I want an IntegrationFlow registered as a Spring bean for each entry found in the above table definition. When a row is added, a new bean is registered, and when a row is deleted, the corresponding bean is destroyed.
I've considered creating an EntityListener for the above entity, in which #PostPersist and #PostRemove will create/destroy IntegrationFlow beans via IntegrationFlowContext, but this solution seemed a bit clunky, and I was wondering if there was any functionality that exists that's a bit more streamlined to solve the above problem. Perhaps some sort of row mapping functionality that can map spring beans to JPA database rows, etc?
Any help would be much appreciated!
thanks,
Monk
Well, such an idea has crossed my mind several times in the past. But even with an XML configuration easily serialized into databased and deserialized into an Integration Flow (XML one) in its own child ApplicationContext, we still ended up with the problem that some beans have to be provided with their Java code. Even if we opted out for Groovy scripts, which could be parsed and loaded at runtime, some Java code would need to be compiled anyway. And in the end when we released some solution for the customer, it became very messy error prone how their operators wrote those dynamic flows.
You definitely can have some external configuration options and can have a conditional logic, but still the code must be compiled in advance without any way to let the logic (not data) to be seriailzed and deserialized at runtime.
Probably this is not an answer you are looking for, but there is no such a serialization solution and possibly it won't be done at all, since it is an anti-pattern (IMHO) to have dynamic application these days when we simply can deal with short and simple microservices or even functions.

Spring Boot + JDBC (not JPA) + Postgres Getting Started?

Try as I might, I cannot seem to find a simple example of a SpringBoot application that uses Spring Data JDBC with a Postgres database, or how to generate Entity classes from a database, or vice versa if that's required, or even how to get a reference to a Data Source.
There are lots of examples using JPA.
There are a few examples spinning up an H2/HSQL on the fly.
There are a couple using Postgres with Spring but not Spring Boot, which means these examples have a number of extra steps.
I believe I know what dependencies are needed -- basically Postgres and a Spring Data JDBC starter, both available in start.spring.io - and as far as data source properties, the example in this this link seems like it might work ...
spring.datasource.url=jdbc:postgresql://localhost:5432/shopme
spring.datasource.username=postgres
spring.datasource.password=password
But I cannot find how to declare a Repository class, or how to instantiate or get a reference to said Repository. If the docs are meant to explain this, I am afraid their virtues are lost on me. From the examples they link to, it looks like perhaps I can create a repository like this ...
interface CategoryRepository extends CrudRepository<Category, Long>, WithInsert<Category> {}
... and then get a reference to an implementation of my repository like this ...
#Autowired CategoryRepository repository;
... and I guess that will use my Postgres info from application.properties somehow.
None of that addresses Table schema => POJO generation (or vice versa). But even if I'm right about the above, this is my persistence layer. I'm not comfortable copy/pasting from some sample code, getting a good result (for now), and declaring it done. I'd rather be working from real information.
If I'm starting with valid Postgres connection info and I know what I want my Entities to look like ...
How do I capture my Postgres connection info in properties? (I suspect my properties example above is correct but that's just copy/paste from some link)
How do I write tables and then generate Entity classes, or the reverse? I prefer the former but I'll settle for either at this point.
How do I get a reference to a DataSource to my Postgres database? (I might never need one but I'd like to know how in case I do)
How do I define a repository class? (I believe I extend CrudRepository<AggRoot, IdType> if I'm happy with CrudRepo, but I'm hazy on this)
How do I instantiate my repo class with my postgres info / DataSource?
How do I get a reference to this repo?
I'm sure a lot of this would be easier if I was stronger with basic Spring, but I am learning that as I go.
Thanks so much!
Bean
I have pieced together some working code from various source and copy/pastes. It does not feel like an answer, so much as it feels like code that happens to work, for now, and I'm open to any suggestions, corrections, or improvements.
How do I capture my Postgres connection info in properties?
This appears to be covered in the Spring Boot docs, not Spring Data etc. There's quite a gotcha around property names that's easy to overlook, which has to do with a Spring Data default connection pool change (Tomcat to Hikari), which requires a subtle property name change: x.y.url= changes to x.y.jdbc-url=. So my properties look like this:
app.datasource.jdbc-url=jdbc:postgresql://localhost:5432/mydb
app.datasource.username=admin
app.datasource.password=admin
How do I write tables and then generate Entity classes, or the reverse? I prefer the former but I'll settle for either at this point.
From what I can tell, in Spring Data JDBC you cannot do either. All I am going off of is something I read in a blog post from 2019 ... I'd love something definitive one way or the other.
How do I get a reference to a DataSource to my Postgres database? (I might never need one but I'd like to know how in case I do)
Using the subtly-documented DataSourceBuilder seems to be the way to go. Even more subtly documented is the need to annotate your DataSourceBuilder with the prefix you're using for your connection string application properties. Easiest is to declare the DataSourceBuilder method in your Application class. The good news is the declaration itself is very simple.
#Bean
#ConfigurationProperties(prefix = "app.datasource")
public DataSource dataSource ()
{
return DataSourceBuilder.create().build();
}
How do I define a repository class? (I believe I extend CrudRepository<AggRoot, IdType> if I'm happy with CrudRepo, but I'm hazy on this)
Indeed, CrudRepository is the way to go. A lot of the examples I found were misleadingly complex: they add annotations because they are doing non-default stuff, but if you just want CRUD, this is all you need:
#Repository // I'm unsure if this is needed - some examples had it, some didn't
public interface MyAggRootRepository extends CrudRepository<MyAggRoot, Long>
{
}
How do I instantiate my repo class with my postgres info / DataSource?
How do I get a reference to this repo?
With a properly coded DataSourceBuilder as above, all you need is to declare an #Autowired field for your repo and you're done.
#Autowired
MyAggRootRepository _repo
That appears to be everything. Once you know the steps there's not much to it:
a few lines in application.properties
a pretty trivial interface extending CrudRepository(T, PK)
a boilerplate DataSource-returning method using DataSourceBuilder (possibly with care taken to get the prefix right on the properties)
a simple #Autowired repository field
The lack of table or Entity class generation means a bit more work, but it's one less thing to know, and one less source of surprises I have to deal with so I don't mind the tradeoff.
If anyone can correct the above, or point to a definitive reference rather than hazy memory of blog posts, feel free.
I just uploaded a basic example of using Spring Data JPA here on my Github (Sorry, that's a lot of line on the application.properties, just ignore if unnecessary)
When you using spring-boot-starter-data-jpa dependency. It will setup anything related to database for you. You don't need to put any boilerplate code.
You can use annotation #Repository or not, it depends on your code structure and requirement. For me, I always use annotation.
If you're using eclipse, you can use a 'Generate Entities from Tables' wizard. Specify a connector or driver, fill out database creadential and you are ready to go.

#EnableJpaRepositories.enableDefaultTransactions = false not working

The JavaDoc reads
Configures whether to enable default transactions for Spring Data JPA repositories. Defaults to true. If disabled, repositories must be used behind a facade that's configuring transactions (e.g. using Spring's annotation driven transaction facilities) or repository methods have to be used to demarcate transactions.
I debugged into the framework, and there it just creates a transaction if none exists, even with enableDefaultTransactions = false.
As far as I can see, Spring Data JPA Repositories are pre-configured with #Transactional(readOnly=true) (see SimpleJpaRepository), which leads to nobody noticing when a programmer forgot to properly annotate his service or job with the proper #Transactional because Spring Data JPA creates a transaction for every repository method that's called.
I wanted to disable it. First try was putting a #Transactional(MANDATORY) on my repository super interface. That wasn't working.
Then I noticed "enableDefaultTransactions" in the #EnableJpaRepositories annotation. I set it to false, but nothing changed. The JavaDoc lead me to believe that it would do exactly what I wanted: to remove the default transaction support and throw an exception when using a repository without already being in a transaction context.
Am I wrong? Is this a bug? Is enableDefaultTransactions intended any other way?
Using spring data jpa 1.9.0.RELEASE.
The intention of enableDataTransactions=false is to remove the default transaction management from the implementation (I guess from SimpleJpaRepository). It will behave as if no #Transactional was specified. Then you can control transactions in the service layer.
https://jira.spring.io/browse/DATAJPA-685
However, regardless of the enableDataTransactions parameter, if you add your own #Transactional annotation in your repository interfaces, it will be correctly applied.
However, however! If you specify #Transactional on the type level, the Spring framework itself (unrelated to data and JPA projects) will apply it only to methods declared in that type, not to the inherited methods. I find this behavior to be correct! Only by overriding the method, you can change its specification and implementation.
#Transactional(propagation=Propagation.MANDATORY)
public interface MyRepository extends CrudRepository<Something, Long> {
#Override
public Something findOne(Long id);
}
In this sample, MANDATORY propagation will apply to findOne, but it won't to findAll.
Note: Even though I find this behavior correct, I still don't like that there is no standard way to configure the MANDATORY propagation globally. In my opinion, it should even be default.
There were bugs with this in previous releases. I used Spring 4.2.2 and Sprint Data 1.11.0 to test it.
Bug reports:
https://jira.spring.io/browse/DATACMNS-715

com.google.web.bindery.requestfactory.shared.Locator.getVersion() - What is this method used for?

I'm writing my first GWT-Application and need your advice. I have no problems implementing a locator for database entities where I can reuse the version-column used for optimistic locking by hibernate, but one of my entities represents a ldap-Object. Can you tell me what the method getVersion() of the Locator is used for and how I can implement this method for my ldap-Object? I will do read and write ldap objects.
From GWT documentation, getVersion method is
Used by RequestFactory to infer if an entity has changed. The backing store (JDO, JPA, etc.) is responsible for updating the version each time the object is persisted, and RequestFactory calls getVersion() to learn of changes. This information is used in two places. First, the RequestFactoryServlet sends an UPDATE event to the client if an entity changes as a result of the method invocation on the server, for example, when a call to persist an editable entity results in an updated version on the server. Second, the client maintains a version cache of recently seen entities. Whenever it sees an entity whose version has changed, it fires UPDATE events on the event bus so that listeners can update the view.
Since many persistence frameworks offer generic find/get/query methods, it's also possible to create a generic Locator class and specify it in the #ProxyFor annotation for each entity type. To do this, all your entities can extend a base class that provides getId() and getVersion(). Alternatively, the generic Locator can use reflection to call getId() and getVersion() when needed.
Not sure if you're looking for anything else in addition to this.
I have the same problem. My first thought was to use the Attribute modifyTimestamp and createTimestamp. But there is still a functional gap:
The smallest unit of These timestamps is seconds so a Change in the same second can not be detected. Another solution would be to use a kind of checksum over all attributes of the ldap object. Not very nice..

How to persist JPA entities even when EJB method throws an exception?

I have an EJB, whose method (among other things) persists JPA entity. If the method throws an error, the transaction is rolled back and the entity is not persisted.
However, I do want that entity to be persisted regardless of any exceptions, that might occur in the EJB method.
I'm using WebSphere 7.0, EJB3.0, JPA 1.0 (OpenJPA that is in WAS), DB2, if it matters.
I tried setting #TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) on top of EJB; with that, entity is not persisted even if there is no exception. I also tried commiting transaction myself (em.getTransaction().commit()), but getTransaction() throws exception (because transactions are managed by container).
Use bean-managed transactions.
#Stateless
#TransactionManagement(TransactionManagementType.BEAN)
public class MyEJB {
#PersistenceContext(unitName="...")
private EntityManager _em;
#Resource
private UserTransaction _utx;
public void myEJBMethod() {
_utx.begin();
// Use _em
_utx.commit();
// Do other work that might throw an exception.
}
}
Alternatively, use TransactionAttributeType.REQUIRES_NEW as suggested by edalorzo.
I am not an expert on EJBs, but I have been dealing with JPA and transactions for a few days now.
I recently answered another question about how entities resided in a context, and how this works in Java EE applications, the context is linked with your JTA transaction.
You can see details of this answer by clicking here. I think it is useful to understand how to context works in order to comprehend the nature of problems like the one you describe.
If you do not provide transaction support, then there is nothing to persist from the container standpoint, and therefore, your changes to the context are transient.
Also you have to consider that once an exception occurs, your context becomes invalid, and the entities in it get detached. (There are a few exceptions to this, like NoResultException).
Thus, from that point on, if you want to commit something, you need a new JTA transaction, with a new fresh JPA context in order to be able to commit changes to the database.
As I said, I am not an expert in EJBs, but if your method fails due to exceptions and you still would like to retry the transaction again by re-invoking the method, then you could force a new transaction to be created every time the method is invoked and by this, you would create a new fresh JPA context.
On the other hand, if you want your modifications to the entities to be persisted, regardless of exceptions in the method, then you might like to consider moving the code that is updating the entities to a new EJB method defined to start a new transaction (TransactionAttributeType.REQUIRES_NEW) every time you invoke it.
By the time this second inner method finishes, your work over the transactions will be automatically flushed to the database, regardless of the outer method of you EJB failing.
Basically, you would be providing a new context for your entities, and linking such context to a new transaction, scoped to commit when the inner method completes.
The natural behavior in EJB containers, as far as I understand, is that ever method joins the already existing transaction, and this is what you might like to prevent, from my point of view.
Another alternative: if you want to control your context using a different transaction support then you might like to consider providing a resource-local based persistence unit and you can manually instantiate your entity manager and control transaction scope as you wish. But honestly, this does not sound like a good idea to me, at least no in the context of the problem that you described.