Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide support for declarative TX and transactional observers #65

Open
gunnarmorling opened this issue Jan 14, 2019 · 19 comments
Open

Comments

@gunnarmorling
Copy link

gunnarmorling commented Jan 14, 2019

Hey, first of all, thanks a lot for this project, it's very helpful!

One thing I was missing is support for declarative TX control (via @Transactional) and transactional observers. This needs JTA to be hooked up.

I figured out the steps needed and added an example to our demos repo in Hibernate: hibernate/hibernate-demos#39

Also planning to write a blog post about this, but actually it'd be great if this was working out-of-the-box in Weld JUnit. I.e. there could be a new module, "persistence" or so, which does all the things I had to do manually:

  • Provide producers for EM and EMF
  • Inject the BM into Hibernate so that DI works in JPA entity listeners
  • Set up JTA via Narayana, bringing support for @Transactional
  • Hooking up TransactionServices so that Weld can make use of JTA and support transactional observers and injection of the UserTransaction

WDYT?

@gunnarmorling
Copy link
Author

@antoinesd, interested in your opinion as well :)

@manovotn
Copy link
Collaborator

I think this would be an interesting yet very specific addition and that it should be an independent feature that you can but don't need to run in your tests.
This gets somewhat trickier in combination with the fact that we need a solution for junit4 and junit5 both of which operate differently.

Ideally, we would have this as separate module, but you will need to somehow access the Weld object we create so that you can register you beans (producers) and transactional service with it (some static method allowing that perhaps?).

If you can cobble together a PR, we can go from there.

@gunnarmorling
Copy link
Author

Ideally, we would have this as separate module

Yes, that was my very thinking, too. By adding this module, a user would get support for JPA/JTA.

If you can cobble together a PR, we can go from there.

That'd be fantastic!

@gunnarmorling
Copy link
Author

gunnarmorling commented Jan 24, 2019

Here's my blog post on the topic which also contains an example implementation:

http://in.relation.to/2019/01/23/testing-cdi-beans-and-persistence-layer-under-java-se/

The code is in the hibernate-demos repo and I've rewritten it slightly now, so everything is easily usable via a JUnit rule. I think you could essentially pull over this rule into a new weld-junit-persistence module and this would already be of great help.

@webczat
Copy link

webczat commented Apr 9, 2019

to be honest, I am wondering why weld just doesn't provide an supposedly optional feature to have a default TransactionServices implementation that looks up transaction related objects via jndi, for example. There are transaction managers that are used in java se apps, and none of them including narayana has provided it's own implementation of this. That would leave only entity manager factory and such like to be done.

@Bukama
Copy link

Bukama commented Mar 22, 2020

Were any further actions done here? I'm heavily struggeling with the transaction context, while trying to adopt @gunnarmorling example to my test project (here executing a very simple CDI Test which looks exactly like in @gunnarmorling project but in my it fails )

INFO: WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
Mär 22, 2020 6:20:07 PM org.jboss.weld.event.ExtensionObserverMethodImpl checkRequiredTypeAnnotations
INFO: WELD-000411: Observer method [BackedAnnotatedMethod] org.jboss.weld.junit5.auto.TestInstanceInjectionExtension.rewriteTestClassScope(@Observes ProcessAnnotatedType<T>, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.


java.lang.NoSuchMethodError: javax.enterprise.inject.spi.ObserverMethod.getPriority()I

I found #80 that this error comes from a older jboss-classfilewriter, but this should be fixed in the weld-unit5 version I use (using currentv2.0.1.Final )

If you want to have a look at my testing project it would be the StringBuilderWeldTest in the EJB module.

@manovotn
Copy link
Collaborator

@Bukama your error is different from what's in #80.

ObserverMethod.getPriority() is CDI 2.0 and weld-junit now supports that (and not 1.2). Are you by any chance overriding that to CDI 1.2? Since I would guess that can be the issue.

@Bukama
Copy link

Bukama commented Mar 23, 2020

@Bukama your error is different from what's in #80.

ObserverMethod.getPriority() is CDI 2.0 and weld-junit now supports that (and not 1.2). Are you by any chance overriding that to CDI 1.2? Since I would guess that can be the issue.

Oh thanks. Sorry if I pollute this thread. In my demo project I'll have JavaEE 7 (so CDI 1.2) application as I'm trying to set up this testing environment for our work situation (yeah Java EE 7 ...). Will try to go back to an older version of weld-junit. If you have any advises feel free to contact me at e.g. twitter (@bukamabish)

@manovotn
Copy link
Collaborator

No problem.
Just note that weld-junit has swapped to CDI 2.0 and any future releases will be targetting that or newer versions. We don't plan to maintain CDI 1.2 support.

@x80486
Copy link

x80486 commented Sep 23, 2024

[...a few years later]

Hi everyone! 👋 ...I came across this thread while trying to integrate a declarative transactional approach in a simple application that uses Weld and Jakarta Persistence.

I wanted to ask if there has been any consideration for introducing support for this in the testing library 🤔

@manovotn
Copy link
Collaborator

[...a few years later]

Hi everyone! 👋 ...I came across this thread while trying to integrate a declarative transactional approach in a simple application that uses Weld and Jakarta Persistence.

I wanted to ask if there has been any consideration for introducing support for this in the testing library 🤔

Hello

there has been no work done in this regard and this issue has mostly been buried and forgotten I am afraid :)
That being said, if you are willing to work on it and send some draft/PR, we can definitely consider this as some form of an optional module for weld-junit.

@x80486
Copy link

x80486 commented Sep 25, 2024

I'm on the other side of the fence for this one because I wouldn't know where to start 😅

I'll leave this one up for a more qualified soul.

Thanks foe the update! 🙌

@manovotn
Copy link
Collaborator

I'm on the other side of the fence for this one because I wouldn't know where to start 😅

I'll leave this one up for a more qualified soul.

Thanks foe the update! 🙌

In one of the earlier comments there is a link to a sample code that has some of the internals we'd use.

Then there's a question of how to include this. If it should be:

  • Part of the core extension and always present
    • Simple to add but you bring some luggage that you don't need for most scenarios
  • Optional enhancement in which case we need a way for user to say this should be included for the test
    • This needs to cover both testing styles - WeldJunit5Extension and WeldJunit5AutoExtension

I'd say it's better to keep it optional but OFC we could start by adding it directly and then taking a look at how much luggage does that amount to.

@manovotn
Copy link
Collaborator

Thinking about it some more, we might be able to re-use (or repurpose) org.jboss.weld.junit5.WeldJunitEnricher - if the optional module had that service implementation, it would be picked up 🤔

@manovotn
Copy link
Collaborator

I tried playing with this a little but my knowledge in the JPA area is pretty much nonexistent so that's making it hard to know what kind of wiring do we need/want. It also does bring in a lot of dependencies - hibernate core parts for JPA bits and Narayana core for JTA.
Furthermore, a dependency on org.jboss.weld.module:weld-jta would be required (in weld-testing) to properly provision a UserTransaction through an implementation of org.jboss.weld.transaction.spi.TransactionServices.

@x80486 do you have a sample (or more) of tests that you would expect to work?
Just to give me a more complete idea of what we'd need to cover.

@x80486
Copy link

x80486 commented Sep 27, 2024

x80486 do you have a sample (or more) of tests that you would expect to work? Just to give me a more complete idea of what we'd need to cover.

Thank you for looking into this 🥇

I'll create a small repository so you can test this — give me a couple of hours to put everything together. It will be everything working in main, and a weld-jta-test branch with the changes using the annotations instead.

@manovotn
Copy link
Collaborator

x80486 do you have a sample (or more) of tests that you would expect to work? Just to give me a more complete idea of what we'd need to cover.

Thank you for looking into this 🥇

I'll create a small repository so you can test this — give me a couple of hours to put everything together. It will be everything working in main, and a weld-jta-test branch with the changes using the annotations instead.

Thank you.
And no need to rush, I probably won't be able to get back to it until early next week :)

@x80486
Copy link

x80486 commented Sep 27, 2024

This is the repository: jakarta-persistence-weld-testing.zip

On main you can run ./gradlew clean check; that will run all test cases successfully.

$ git status 
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean
$ ./gradlew clean check 
To honour the JVM settings for this build a single-use Daemon process will be forked. For more on this, please refer to https://docs.gradle.org/8.10.2/userguide/gradle_daemon.html#sec:disabling_the_daemon in the Gradle documentation.
Daemon will be stopped at the end of the build 
> Task :clean
> Task :processResources
> Task :processTestResources
> Task :generateEffectiveLombokConfig
> Task :compileJava
> Task :classes
> Task :generateTestEffectiveLombokConfig
> Task :compileTestJava
> Task :testClasses
> Task :test
> Task :check

BUILD SUCCESSFUL in 7s
8 actionable tasks: 8 executed

If you change to the branch weld-jta-test and repeat the same process you will see some failures — I think it's because currently the @Transactional annotation has no effect when the Weld container starts and wires up everything.

$ git checkout weld-jta-test 
Switched to branch 'weld-jta-test'
Your branch is up to date with 'origin/weld-jta-test'.
$ ./gradlew clean check 
To honour the JVM settings for this build a single-use Daemon process will be forked. For more on this, please refer to https://docs.gradle.org/8.10.2/userguide/gradle_daemon.html#sec:disabling_the_daemon in the Gradle documentation.
Daemon will be stopped at the end of the build 
> Task :clean
> Task :processResources
> Task :processTestResources
> Task :generateEffectiveLombokConfig
> Task :compileJava
> Task :classes
> Task :generateTestEffectiveLombokConfig
> Task :compileTestJava
> Task :testClasses

> Task :test FAILED

MyEntityRepositoryTest > saveFindAndUpdate() FAILED
    java.lang.AssertionError at MyEntityRepositoryTest.java:72

MyEntityRepositoryTest > save() FAILED
    java.lang.AssertionError at MyEntityRepositoryTest.java:42

6 tests completed, 2 failed

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':test'.
> There were failing tests. See the report at: file:///.../jakarta-persistence-weld-testing/build/reports/tests/test/index.html

* Try:
> Run with --scan to get full insights.

BUILD FAILED in 6s
8 actionable tasks: 8 executed

@gunnarmorling could validate this example as well.

@manovotn
Copy link
Collaborator

I see, thanks @x80486

I can see you are handling JPA and actually only need JTA bits.
You could add those (well, most of them) by annotating the test with:

import com.arjuna.ats.jta.cdi.TransactionExtension;
// more imports...

@EnableAutoWeld
@AddBeanClasses(EntityManagerProducer.class)
@AddExtensions(TransactionExtension.class)
final class MyEntityRepositoryTest {
// test itself...

For which you need a dependency on narayana, so in gradle speech that should be something like testImplementation("org.jboss.narayana.jta:narayana-jta:7.0.2.Final").

But that seems to leave two tests failing and in both cases it seems that saved entity then cannot be found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants