Wiki source code of IPluginEntities


Show last authors
1 {{content/}}
2
3 == Interface IPluginEntities ==
4
5 {{figure image="plugin_entities_demo.png"}}
6 A sample entities plugin that adds a single entity named //ProgrammingLanguage//. To the left hand side, you can see the new database table that was created in the same database used by {{formcycle/}}. To the right hand side, a simple portal plugin illustrates how this entity can be used. The portal page shows a list of all available programming languages and also lets the user create new languages.
7 {{/figure}}
8
9 The interface for an entities plugin. This type of plugin lets you add custom JPA (Java persistence API) entities to {{formcycle/}}. You can then use these entities within other plugins, such as //IPluginPortal// or [[IPluginFormPreRender>>doc:IPluginFormPreRender]]. One common use case are portal plugins with or without //IPluginMenuEntries// that need to save configuration data or a list of items in the database. Please note that plugin entities are not supported on a frontend server - they will work only on a master server.
10
11 Each entities plugin consists of the following components:
12
13 * one or multiple entity classes that must have the {{jpath path="javax.persistence.Entity"/}} annotation
14 * a [[Liquibase>>url:http://www.liquibase.org]] script that creates the required database tables and can be used for updates, and
15 * a {{jpath path="javax.sql.DataSource"/}} with the connection details to a database (defaults to the FORMCYCLE database)
16
17 The entity classes are picked up automatically as long as they are annotated with the {{jpath path="javax.persistence.Entity"/}} annotation.
18
19 {{info}}
20 Important: Do not set up any hard references between a plugin entity and a {{formcycle/}} entity, or between entities of different plugins. A hard reference between two entities is established by an annotation such as {{jpath path="javax.persistence.OneToMany"/}} or {{jpath path="javax.persistence.ManyToMany"/}} etc. You can, however, add references between entities of a single entities plugin. This limitation exists because a separate {{jpath path="javax.persistence.EntityManager"/}} needs to be used for each plugin; and an entity manager do not know about the entities available to another entity manager. If you need to reference {{formcycle/}} entities, considers using soft references (that is, just saving the //IEntity.getId()// or //IUUIDEntity.getUUID()// of an entity without a foreign key constraint).
21
22 Also, note that it would be possible to add a foreign key constraint in the database between a plugin entity and a {{formcycle/}} entity. This is not officially supported and should be avoided as it creates unnecessary dependencies, violates plugin isolation, makes it harder to migrate an entities plugin to a different database, and may break with future updates of {{formcycle/}}.
23 {{/info}}
24
25 === Use cases ===
26
27 * Save configuration data by portal or another plugin
28 * Save items required for a portal view
29
30 {{warning}}
31 If you choose to save the entities in the same database that is used by the {{formcycle/}} system, make sure you use unique names that do not conflict with existing names used by {{formcycle/}}. This includes table names, but also other names such as foreign or primary key constraints as well as the ID for the Liquibase changeset.
32 {{/warning}}
33
34 === Method signatures ===
35
36 {{panel title="{{code language='java'~}~}default IPluginEntitiesConnectionRetVal getConnectionDetails(){{/code~}~}" triggerable="true" fullwidth="true" styleClass="xm-code-panel"}}
37 (((
38 By default, plugin entities are saved in the system database, ie the same database that {{formcycle/}} uses. In this case, make sure the table names for the plugin entities do not collide with any pre-existing {{formcycle/}} table names. We recommend you add a custom prefix to each table name.
39 )))
40
41 {{html}}<br>{{/html}}
42
43 (((
44 If necessary, you can override this method and return custom connection details for connecting to a different database where you would like to save the plugin entities.
45 )))
46
47 ; Return value
48 : The connection details to the database that will store the plugin entities. If //null//, the system database of {{formcycle/}} is used.
49 {{/panel}}
50
51 {{panel title="{{code language='java'~}~}default List<String> getLiquibaseScripts(){{/code~}~}" triggerable="true" fullwidth="true" styleClass="xm-code-panel"}}
52 (((
53 This method may be used to return a list of Liquibase scripts for initializing or updating the database. The Liquibase scripts are run in the order as returned by this method. A Liquibase scripts consists of a list of change sets. Each changeset is responsible for a single logical database modification, such as creating a table or adding some new columns to a table. If an empty list is returned, no Liquibase script are run.
54 )))
55
56 {{html}}<br>{{/html}}
57
58 (((
59 When the plugin is installed for the first time, the scripts are run to create the initial database configuration. Then, when this plugin is updated to a new version and you need to update the database as well, you can add additional change sets to the Liquibase script. All change sets that were run already will not be run again. For this to work, make sure you do not modify any existing change sets, as Liquibase creates a hash of the source code of each change set.
60 )))
61
62 {{html}}<br>{{/html}}
63
64 (((
65 In some cases, your database setup may depend on the version of {{formcycle/}}. If so, and you want to run certain Liquibase scripts only for certain versions, you can check which version of {{formcycle/}} is currently installed via {{jpath path="de.xima.fc.VersionsInfo"/}}#sdkVersion.
66 )))
67
68 {{html}}<br>{{/html}}
69
70 (((
71 For more information, refer to the [[documentation pages of Liquibase>>url:https://www.liquibase.org/documentation/changeset.html]].
72 )))
73
74 ; Return value
75 : A list of Liquibase scripts for initializing or updating the database. May be an empty list in case you need to set up the database. Each entry must be a path to a Liquibase XML file, in the format accepted by {{jpath path="java.lang.ClassLoader"/}}#getResources.
76
77 {{/panel}}
78
79 {{panel title="{{code language='java'~}~}void onDatabaseReady(IPluginEntitiesParams params) throws FCPluginException{{/code~}~}" triggerable="true" fullwidth="true" styleClass="xm-code-panel"}}
80
81 (((
82 This callback method is invoked after the plugin was initialized and after the database was set up and is ready to be used. You may use the {{jpath path="javax.persistence.EntityManagerFactory"/}} that passed to this method to create new entities or fetch, update and delete existing ones. This is normally done by creating a new {{jpath path="javax.persistence.EntityManager"/}} via {{jpath path="javax.persistence.EntityManagerFactory"/}}#createEntityManager.
83 )))
84
85 {{html}}<br>{{/html}}
86
87 (((
88 However, you may find the API offered by the EntityManager hard to use. If so, you can use the DAO (database access objects) API provided by {{formcycle/}} to work with your entities more easily. First, use //IPluginEntitiesParams#getPluginEmManager// and save the EM manager in a static field for later use in a bean or a filter. Later, when you need to access the database, use {{jpath path="de.xima.fc.interfaces.plugin.param.entities.IPluginEmManager"/}}#newEntityContext to create a new entity context and pass this context to the methods offered by {{jpath path="de.xima.cmn.dao.interfaces.IAbstractDao"/}}. For example, when you have got an entity class //MyEntity// and want to retrieve a list of all entities:
89 )))
90
91 {{html}}<br>{{/html}}
92
93 (((
94 {{code language="java"}}
95 try (final IBaseEntityContext ec = pluginEmManager.newEntityContext()) {
96 // use entity context with some DAO
97 // this fetches all existing MyEntity
98 new AbstractDao(MyEntity.class) {}.all(null, new QueryCriteriaManager());
99 }
100 {{/code}}
101 )))
102
103 {{html}}<br>{{/html}}
104
105 (((
106 If you only want to retrieve a subset of entities matching a certain criterion, use the {{jpath path="de.xima.cmn.criteria.QueryCriteriaManager"/}} API offered by {{formcycle/}}. Finally, instead of creating a new DAO on the fly, consider creating your own DAO classes by extending {{jpath path="de.xima.cmn.dao.interfaces.IAbstractDao"/}}.
107 )))
108
109 ; Parameters
110 : This method takes the following parameters:
111 :; params
112 :: The parameters this method may make use of. Contains the {{jpath path="javax.persistence.EntityManagerFactory"/}}} for working with the entities, as well as the {{jpath path="de.xima.fc.interfaces.plugin.param.entities.IPluginEmManager"/}} to make that work easier.
113 ; Throws
114 : This method is allowed to throw the following exceptions:
115 :; FCPluginException
116 :: When this method performs an initial setup, such as creating new entities, and that setup fails. If that exception is thrown, this plugin will be deactivated and not put into service.
117 {{/panel}}