Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-dev] Dynamic persistence unit

> - does it mean that all the annotated (say, with @Entity) classes will be added to the empty pu?
The empty pu is only used for weaving. It isn't used to create a proper EntityManagerFactory. I don't entirely know how the transformer works, but I assume it is smart enough to know that it's persistence unit is defined with <exclude-unlisted-classes>false so it will enhance anything with an @Entity annotation. Obviously this breaks down somewhat if you are defining anything in an orm.xml... but I think that is a solvable problem. I'm digressing here, but I think anytime you need to use an orm.xml file for a testcase, it'll need to be added to this 'empty' / weaving only pu.

> - the whole process will be repeated each time createEntityManagerFactory is called;
I don't follow. A transformer should only be registered on the premain called. 

> - how do we ever create a regular pu (seem like never go past this nameless one) 
I'm not entirely sure I follow this comment, but I'll give it a shot... currently there isn't any support for using a 'normal' persistence unit that is defined in a persistence.xml. It would be easy enough to add something like this if it was required though.

> -- I guess we could only use the new code if puName==null;
The only time this new 'dynamic persistence unit' support kicks in is if you pass a SEPersistenceUnitInfo in the properties map on a .createEntityManagerFactory call.

> - worse yet, if the class is already loaded dynamic weaving won't work (too late):
I think that would happen if you use a static variable   static Dog myDog = new Dog("My"); that forces to class to load.
I don't think this is comment is entirely correct. When using the javaagent, the transformer gets loaded/registered prior to any test classes / Entities being loaded so that shouldn't be a problem.  

Attached to this email is a working copy of what I'm proposing. Go ahead an unzip it into eclipselink.runtime\jpa and give it a run. You should be able to import it directly into Eclipse also. To run in Eclipse you'll need to set the db connection details / -javaagent as jvm args. Note that the TestInheritancePrePersist test is currently failing.

File -- http://filebin.ca/1eWfY4LPW64G/eclipselink.jpa.test.jse.zip

Thanks,
Rick

On Tue, Oct 21, 2014 at 12:52 PM, andrei ilitchev <andrei.ilitchev@xxxxxxxxxx> wrote:
- does it mean that all the annotated (say, with @Entity) classes will be added to the empty pu?
- the whole process will be repeated each time createEntityManagerFactory is called;
- how do we ever create a regular pu (seem like never go past this nameless one)
-- I guess we could only use the new code if puName==null;
- worse yet, if the class is already loaded dynamic weaving won't work (too late):
I think that would happen if you use a static variable
  static Dog myDog = new Dog("My");
that forces to class to load.

Thanks,
Andrei
...
On 10/21/2014 12:22 PM, Rick Curtis wrote:
How does the agent know which classes to weave?
Ah, an empty persistence unit with <exclude-unlisted-classes>false</exclude-unlisted-classes>... with the hope that the agent will weave classes as they are loaded and it won't eagerly load all classes looking for Entities to enhance.

On Tue, Oct 21, 2014 at 11:09 AM, andrei ilitchev <andrei.ilitchev@xxxxxxxxxx> wrote:
I am confused, too.
How does the agent know which classes to weave?
On 10/21/2014 12:03 PM, Rick Curtis wrote:
However dynamic weaving is not possible (try LAZY OneToOne - it requires weaving).
I'm confused. Does dynamic weaving == -javaagent weaving? 

If so, I thought that is a valid form of weaving?.... and my testing shows that the agent does enable lazy loading.


On Tue, Oct 21, 2014 at 10:35 AM, andrei ilitchev <andrei.ilitchev@xxxxxxxxxx> wrote:
I agree it's not a problem with statically weaved classes.
However dynamic weaving is not possible (try LAZY OneToOne - it requires weaving).
Thanks,
Andrei

On 10/21/2014 11:29 AM, Rick Curtis wrote:
Not a problem since Entities are statically weaved as part of the build. This could be an issue if you needed to test something with a non-standard weaving configuration, but that is fixable by adding some more bits to the build script. When running the tests in Eclipse the -javaagent should work.

Thanks,
Rick

On Tue, Oct 21, 2014 at 8:36 AM, andrei ilitchev <andrei.ilitchev@xxxxxxxxxx> wrote:
I think the biggest problem with this approach
    @Emf(classes = { Dog.class, XmlFish.class },
is that the classes already loaded, therefore weaving is impossible.

On 10/17/2014 4:49 PM, Rick Curtis wrote:
I spent some more time on this today and came up with the following. I created a new @Emf annotation that a testcase can use in conjunction with a custom test runner that will dynamically create(and inject) a persistence unit depending on the annotated configuration. The test runner is responsible for translating the Emf annotation into a SEPersistenceUnitInfo. Note that a persistence.xml is required, nor is one used for this testing.

Also as I posted in my previous note, I would still like someone to take a look at the JPAInitializer change that I'll need to introduce for this to work. Attached is a patch of the new test framework and a small test case. I also fixed some of the build problems I had in my previous patch. If I get a thumbs up on the runtime changes required for this, I'll go ahead and get something delivered so others can start to kick the tires.

Example :

@RunWith(EmfRunner.class)
public class TestBasicPersistence {
    @Emf(classes = { Dog.class, XmlFish.class },
            properties = { @Property(name = "name", value = "value")},
            mappingFiles= {"META-INF/fish-orm.xml"})
    private EntityManagerFactory emf;


On Wed, Oct 15, 2014 at 4:38 PM, Rick Curtis <curtisr7@xxxxxxxxx> wrote:
Thanks for taking a look at the patch. I investigated using annotations rather than inheritance and that looks like a pretty trivial(and ideal) change. Also, don't worry too much about the build messiness. I know there are problems as it was mostly a late night hack job. I'll get it cleaned up for general consumption before I commit anything.

It could perhaps also get us on the path to make persistence.xml optional at some point - at least for some simple cases...

Please take a closer look at the runtime.patch (specifically JPAInitializer) I posted previously. This is the one aspect I am most concerned with about the changes I'm proposing. This change opens the door to having a persistence.xml-less persistence unit via passing a fully populated SEPersistenceUnitInfo on createEntityManagerFactory. I fear that this small change adds something 
fairly large functionality wise to EclipseLink and someone else with more experience needs to look at the safety of what I'm doing.

Thanks,
Rick

On Sun, Oct 12, 2014 at 12:27 PM, Lukas Jungmann <lukas.jungmann@xxxxxxxxxx> wrote:

On 10/9/14 8:01 PM, Rick Curtis wrote:
Ie it would be nice if the test could be written following way but I'm really not sure if that's doable and what pros/cons this approach would have - it's just an idea:
I too am not certain how doable it would be to use annotations rather than overridden methods. I can take a look though.

that would be great and it should not be difficult if the annotation would have  RetentionPolicy.RUNTIME. It could perhaps also get us on the path to make persistence.xml optional at some point - at least for some simple cases...


Have you had time to take a look yet? I'd like to get some sort of conscientious whether this change is something that I should move forward with.
yes, finally. I like the way it simplifies writing, building and running tests - no more "magic" buried in the build scripts, but the build part requires some work to be following the convention used through the project (ie using junit.lib property instead of referring to ECLIPSE_HOME as not all people working on EL do have Eclipse installed, making sure 'test' from cmd line works etc). OTOH I would still prefer if we could get rid of required inheritance from AbstractJPATest and allow people to inherit from whatever test/class they want if there's a need.

Thanks,
--lukas



On Wed, Oct 1, 2014 at 6:03 PM, Lukas Jungmann <lukas.jungmann@xxxxxxxxxx> wrote:
Hi Rick,

comments inline ...

On 10/1/14 11:11 PM, Rick Curtis wrote:
I finally had a few spare cycles the past couple days and put together a prototype test component. At this point all of this is flexible, but I want to get a feeling from others whether a change like this would be welcomed. I'll note that I did some hacking/poaching from the eclipselink.jpa.test build to get things working. I'm not a build guy, but I wanted to get something that generally works... so don't get too hung up on the build pieces.

as long as it works, it's fine at this stage and we have something 'real' to discuss :-)


My end goal is to have a framework that makes it very easy for someone to create a new jse JPA test. I want to stress that this new component won't be an end-all be-all test component.  The point of it is that anyone with JPA experience can easily and quickly create a JUnit test that can test a large majority of the runtime. That being said, there are certainly some aspects of the runtime that this component will not be able to test. 

A few things to note about this component :
* It uses a single static weaving configuration. That could change in the future if cases come up, but at this point it isn't necessary. When the tests run via ant Entities will be enhanced at compile time. You can also easily use the -javaagent to enhance while running in Eclipse.
* It is NOT targeted to run in an app server
* For most test cases a persistence unit defined in a persistence.xml is not required.
* It depends on eclipselink.ddl-generation for table generation.

Attached below are a couple patches that have the entire change, but I'll give a quick summary.

To create a new testcase :
* Define your Entity model. Entities/embeddables/etc must be in a *.model package
* Define a Test class (in a *.test package) that extends AbstractJPATest. You must implement the getManagedTypes() method to return the Entities that your testcase is using. This method is analogous to the <class> section in a p.xml.

this leads me to the question - why not Maven - or at least not following its convention? I mean it has that convention to have 'real' classes in src/main/java, and tests in src/test/java and we have some model which we want to test..., one project per feature/bug,...- you get the point. I've tried to split current 'monolithic' e.core.test module this way already but had to put that aside for a while (as it is quite complicated/time-consuming due to many dependencies there). OTOH you are creating sth new, so maybe you could give it a try?

* Optionally override the getPersistentProperties() method to return an array of persistence properties your test might need to use.

If this is a configuration thing, maybe some annotation instead of a method to be overridden would be better.

Ie it would be nice if the test could be written following way but I'm really not sure if that's doable and what pros/cons this approach would have - it's just an idea:


@PUConfig(
   props={@Property(name="eclipselink.log", value="FINE")},
   entities={ChildEntity.class, ParentEntity.class})
public class TestInheritancePrePersist {

    @Test
    public void testMultiplePrePersist() {
        EntityManagerFactory emf = AbstractJPATest.getEntityManagerFactory(TestInheritancePrePersist.class);
        ....
    }


Haven't tried your patches yet but hopefully will be able to give it a shot later this week..

thanks,
--lukas


* In each test method, there is an instance variable 'emf' that is based off the properties provided by your test class. 
* Test cases need to ensure that EMs are cleaned up properly
* AbstractJPATest should clean up tables after test classes complete, but it doesn't yet.

To run a new testcase:
* Either run the default target in eclipselink.test.jpa.jse, providing db connection details in test.properties
* To run in Eclipse, provide db connection details as SystemProperties -Djavax.blah bah

Example test :

public class TestInheritancePrePersist extends AbstractJPATest {
    @Override
    public Class<?>[] getManagedTypes() {
        return new Class<?>[] { ChildEntity.class, ParentEntity.class };
    }

    @Override
    public String[] getPersistentProperties() {
        return new String[] { "eclipselink.log", "FINE" };
    }

    @Test
    public void testMultiplePrePersist() {
        EntityManager em = emf.createEntityManager();
        try {
            em.getTransaction().begin();
            ChildEntity ce = new ChildEntity();
            em.persist(ce);

            em.getTransaction().commit();

            em.clear();
            Assert.assertEquals(1, ce.getPrePersistChild());
            Assert.assertEquals(1, ce.getPrePersistParent());
        } finally {
            if (em.getTransaction().isActive()) {
                em.getTransaction().rollback();
            }
            em.close();
        }
    }
...


Wow, that email got a lot longer than I intended. Anyway, I'm looking for a thumbs up / thumbs down on the direction I'm heading. If thumbs up, I'll start committing some code to master later this week.

Thanks,
Rick



On Wed, Sep 10, 2014 at 11:29 AM, Rick Curtis <curtisr7@xxxxxxxxx> wrote:
1. Byte-code weaving of the domain classes. In the standard class-loader configuration the domain classes will be woven once and only once. If this weaving is consistent across all persistence units and test that might share the domain class then you are fine but if the same class is used differently in different PUs then you will be challenged to have separate woven instances of the class isolated by the PU/test-case.

I figured this would be the case. I'm looking more at the middle of the road case. I assume a huge majority of cases can be covered with a default weaving configuration? That being said, I'm not very familiar with the EclipseLink weaving options to know how many different switches there are and how many of them are used in the wild.

there is also the fundamental case that you are now testing a configuration that is separate from the JPA specified one.

True. Testing in this manner would exclude handling / parsing of p.xml files etc, but it would make adding tests for the rest of the runtime much simpler. 

I do have a number of dynamic PU examples I had built locally that I will review and see how best to share.

I'd appreciate you sharing those. I assume these examples use features that are already a part of EclipseLink?

On Wed, Sep 10, 2014 at 10:35 AM, douglas clarke <douglas.clarke@xxxxxxxxxx> wrote:
Rick,

We have done a lot of work with respect to dynamic persistence units addressing both creating PUs on the fly based on concrete Java classes as well as scenarios where the domain classes themselves are created on the fly using byte-code generation.

There are two concerns I see with dynamic PUs for testing:

1. Byte-code weaving of the domain classes. In the standard class-loader configuration the domain classes will be woven once and only once. If this weaving is consistent across all persistence units and test that might share the domain class then you are fine but if the same class is used differently in different PUs then you will be challenged to have separate woven instances of the class isolated by the PU/test-case.

2. We did look at a number of ways to simplify this early on including a custom property for where the persistence.xml file is read from so that we could have a flat classpath for all test cases and supporting PUs. Besides the weaving issue in #1 there is also the fundamental case that you are now testing a configuration that is separate from the JPA specified one. This may be acceptable if managed correctly and there are adequate 'pure JPA' test cases in addition to the compliance tests.

I do have a number of dynamic PU examples I had built locally that I will review and see how best to share.

Doug



On 2014-09-09, 9:17 PM, Rick Curtis wrote:
All -

For a while now, I have wanted an easier way to test EclipseLink and tonight I finally found a few spare cycles to look at this problem. I have been looking for a way to easily create a persistence unit that only exists for the scope of an individual test. I did some poking around and found that without too many changes, I could update JPAInitializer so that a user to could create a SEPersistenceUnitInfo and pass that in as a persistence property on a .createEntityManagerFactory(....) call. This means that you could create an EMF without the requirement of having a p.xml file... the largest drawback I can see at this point is that this data structure is marked as internal, so I don't know if it is kosher to expose outside of the runtime.

Thoughts on going down this road? If I don't hear anything negative, I'll get a bug opened soon and post an initial patch.

--
Rick Curtis


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev



--
Rick Curtis



--
Rick Curtis


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev



--
Rick Curtis


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev



--
Rick Curtis



--
Rick Curtis


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev



--
Rick Curtis


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev



--
Rick Curtis


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev



--
Rick Curtis


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev


_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev



--
Rick Curtis

Back to the top