Ticket #698 (closed Enhancement: fixed)

Opened 5 years ago

Last modified 5 years ago

Plugin framework: create transactions by annotation

Reported by: jri Owned by: jri
Priority: Major Milestone: Release 4.4
Component: DeepaMehta Standard Distribution Version: 4.3
Keywords: Cc: dgf, Malte, carolina
Complexity: 5 Area: Application Framework / API
Module: deepamehta-core

Description

The plugin developer should not be required to create transactions imperatively. Instead she should create a transaction just by annotating a resource method. (A resource method is one with a method designator like @GET.) The DM Core should take provisions to "wrap" such an annotated method within a transaction automatically.

Current pattern (DM 4.3):

    import de.deepamehta.core.storage.spi.DeepaMehtaTransaction;

    public void aResourceMethod() {
        DeepaMehtaTransaction tx = dms.beginTx();
        try {
            ...
            tx.success();
        } catch (Exception e) {
            logger.warning("ROLLBACK!");
            throw new RuntimeException("Something failed", e);
        } finally {
            tx.finish();
        }
    }

New pattern:

    import de.deepamehta.core.service.Transactional;

    @Transactional
    public void aResourceMethod() {
        ...
    }

So, the new pattern would remove a reasonable amount of boilerplate code.

Change History

comment:1 Changed 5 years ago by jri

  • Status changed from new to accepted

comment:2 Changed 5 years ago by Jörg Richter

Core: create transactions by annotation (#698).

A plugin developer can create a transaction just by annotating a resource method. (A resource method is one with a method designator like @GET.) The DM Core takes provisions to "wrap" such an annotated method within a transaction automatically.

Example:

    import de.deepamehta.core.service.Transactional;

    @Transactional
    public void aResourceMethod() {
        ...
    }

See #698.

comment:3 Changed 5 years ago by Jörg Richter

Adapt to Core change (@Transactional) (#698).

The DM distro plugins make use of the new @Transactional annotation.

PLUGIN DEVELOPMENT NOTES

Keep in mind that the Core Service methods (called via the dms object) do not create a transaction on its own anymore (but the corresponding resource methods of the Webservice plugin do). So, when your plugin encounters a NotInTransactionException exception just annotate your originally calling resource method with @Transactional. (A resource method is one with a method designator like @GET.)

Example:

import de.deepamehta.core.service.Transactional;

@Transactional
public void aResourceMethod() {
    ...
}

Note that the majority of your plugin methods are triggered originally by an HTTP request (directly or indirectly), that is a resource method. Annotating that resource method is sufficient. (In fact @Transactional annotations on non-resource methods are ignored.) Most plugins are not required to create a transaction imperatively anymore.

However, there are cases when your plugin methods are *not* triggered by a HTTP request. These cases include

  • the allPluginsActive() event handler
  • tests
  • DM service calls from non-DM OSGi bundles

In these cases you're required to create the transaction imperatively, just as you did before:

    import de.deepamehta.core.storage.spi.DeepaMehtaTransaction;

    public void aMethod() {
        DeepaMehtaTransaction tx = dms.beginTx();
        try {
            ...
            tx.success();
        } catch (Exception e) {
            logger.warning("ROLLBACK!");
            throw new RuntimeException("Something failed", e);
        } finally {
            tx.finish();
        }
    }

Note: calling a @Transactional annotated resource method from another @Transactional annotated resource method is OK. No nested transaction will be created. (Nested transactions are not problematic anyway.) Keep in mind a transaction is only created for the resource method the original HTTP request is mapped to. So, typically there is a 1:1 relationship between transaction and HTTP request.

See #698.

comment:4 Changed 5 years ago by Jörg Richter

Core: create transactions by annotation (#698).

A plugin developer can create a transaction just by annotating a resource method. (A resource method is one with a method designator like @GET.) The DM Core takes provisions to "wrap" such an annotated method within a transaction automatically.

Example:

    import de.deepamehta.core.service.Transactional;

    @Transactional
    public void aResourceMethod() {
        ...
    }

See #698.

comment:5 Changed 5 years ago by Jörg Richter

Adapt to Core change (@Transactional) (#698).

The DM distro plugins make use of the new @Transactional annotation.

PLUGIN DEVELOPMENT NOTES

Keep in mind that the Core Service methods (called via the dms object) do not create a transaction on its own anymore (but the corresponding resource methods of the Webservice plugin do). So, when your plugin encounters a NotInTransactionException exception just annotate your originally calling resource method with @Transactional. (A resource method is one with a method designator like @GET.)

Example:

import de.deepamehta.core.service.Transactional;

@Transactional
public void aResourceMethod() {
    ...
}

Note that the majority of your plugin methods are triggered originally by an HTTP request (directly or indirectly), that is a resource method. Annotating that resource method is sufficient. (In fact @Transactional annotations on non-resource methods are ignored.) Most plugins are not required to create a transaction imperatively anymore.

However, there are cases when your plugin methods are *not* triggered by a HTTP request. These cases include

  • the allPluginsActive() event handler
  • tests
  • DM service calls from non-DM OSGi bundles

In these cases you're required to create the transaction imperatively, just as you did before:

    import de.deepamehta.core.storage.spi.DeepaMehtaTransaction;

    public void aMethod() {
        DeepaMehtaTransaction tx = dms.beginTx();
        try {
            ...
            tx.success();
        } catch (Exception e) {
            logger.warning("ROLLBACK!");
            throw new RuntimeException("Something failed", e);
        } finally {
            tx.finish();
        }
    }

Note: calling a @Transactional annotated resource method from another @Transactional annotated resource method is OK. No nested transaction will be created. (Nested transactions are not problematic anyway.) Keep in mind a transaction is only created for the resource method the original HTTP request is mapped to. So, typically there is a 1:1 relationship between transaction and HTTP request.

See #698.

comment:6 Changed 5 years ago by Jörg Richter

Core: create transactions by annotation (#698).

A plugin developer can create a transaction just by annotating a resource method. (A resource method is one with a method designator like @GET.) The DM Core takes provisions to "wrap" such an annotated method within a transaction automatically.

Example:

    import de.deepamehta.core.service.Transactional;

    @Transactional
    public void aResourceMethod() {
        ...
    }

See #698.

comment:7 Changed 5 years ago by Jörg Richter

Adapt to Core change (@Transactional) (#698).

The DM distro plugins make use of the new @Transactional annotation.

PLUGIN DEVELOPMENT NOTES

Keep in mind that the Core Service methods (called via the dms object) do not create a transaction on its own anymore (but the corresponding resource methods of the Webservice plugin do). So, when your plugin encounters a NotInTransactionException exception just annotate your originally calling resource method with @Transactional. (A resource method is one with a method designator like @GET.)

Example:

import de.deepamehta.core.service.Transactional;

@Transactional
public void aResourceMethod() {
    ...
}

Note that the majority of your plugin methods are triggered originally by an HTTP request (directly or indirectly), that is a resource method. Annotating that resource method is sufficient. (In fact @Transactional annotations on non-resource methods are ignored.) Most plugins are not required to create a transaction imperatively anymore.

However, there are cases when your plugin methods are *not* triggered by a HTTP request. These cases include

  • the allPluginsActive() event handler
  • tests
  • DM service calls from non-DM OSGi bundles

In these cases you're required to create the transaction imperatively, just as you did before:

    import de.deepamehta.core.storage.spi.DeepaMehtaTransaction;

    public void aMethod() {
        DeepaMehtaTransaction tx = dms.beginTx();
        try {
            ...
            tx.success();
        } catch (Exception e) {
            logger.warning("ROLLBACK!");
            throw new RuntimeException("Something failed", e);
        } finally {
            tx.finish();
        }
    }

Note: calling a @Transactional annotated resource method from another @Transactional annotated resource method is OK. No nested transaction will be created. (Nested transactions are not problematic anyway.) Keep in mind a transaction is only created for the resource method the original HTTP request is mapped to. So, typically there is a 1:1 relationship between transaction and HTTP request.

See #698.

comment:8 Changed 5 years ago by jri

  • Status changed from accepted to closed
  • Resolution set to fixed
Note: See TracTickets for help on using tickets.