Development notes
The setup of a Joty Workstation application Eclipse project
It is advisable to start working with the desktop / client-server running mode as target asset (to have this chance is the plus of the technology); anyway for sake of conciseness let's name this asset with the literal D/C-S mode as opposed to web mode.
The following are the steps to be carried on:
- Optional - The insertion of the org.joty.jotyplugin.jar file in the 'plugins' directory of the Eclipse installation directory.
- Optional - The import of the Joty toolbox in to the workspace (extract it, first).
- The creation of a new Java application project.
- Conversion of project into a Maven project
- Addition of the required dependencies to the pom.xml file - you find them here.
- Then in D/C-S mode, the following objects must be placed in the project folder
(see Joty Workstation application guide section for their customization and composition):
- the configuration file 'Joty.xml' (that one appropriated to the chosen dbms type among Oracle, MySql and MS Sql Server - here is that one of the "Mars Explorers" sample application) else 'Joty perceives' the web mode - it is strongly recommended to set its 'debug' item to true
- the 'lang' directory
- The creation of the Java package: for example 'myJotyApp'
- The creation of the application class as a Java class derived from org.joty.workstation.app.Application class; here is an example:
- The creation of the Java package for the db manager implementation class: for example 'myJotyApp.common'
- The creation in that package of the db manager class, as a Java class derived from org.joty.common.DbManager class
- the setting of the 'dbManagerClass' item accordingly to the full name of the created class
- The src/res directory with the application 16 and 32 icons as named in the configuration file and the correspondig setting of the 'appIconFile16' and 'appIconFile32' items of the configuration file with their file names
- The creation of the database with at least the following tables defined:
- appuser
- role
- userrole
- This leads to customize the configuration file for the following items:
- connection-url
- dbmsUserGrantedRolesStmnt
- dbmsSessionPreset
- Then, the first Joty visual class can be created as extension of the org.joty.workstation.gui.DataAccessDialog class and this is the opportunity to open the WindowBuilder designer and to load the Joty Toolbox.
- See odontior2-application sample for a complete example of Joty application
Desktop dbms based application : the conversion in the Joty technology - Considerations
This kind of application is the best candidate to the transformation.
Ideally no change is to be done on the database and all the efforts are forwarded to the analysis of the original code.
Assumed that no hard obstacle is encountered in discovering the management of the connection to the dbms, scenario that is encapsulated in the corresponding implementation of the basic class shown above, every visual object of the application that makes access to the database is the target of the analysis.
For each of such objects an inspecting in the class hierarchy of the Joty framework is advised, starting from the org.joty.workstation.gui.DataAccessDialog root class and going down along its descendants until the best fit is reached either about the layout or about the data management, obviously the perfect match is not searched but only a template that lets see pour effort for further development.
The same process advised for the internal data panels that compose the data dialog, here starting from the org.joty.workstation.gui.DataAccessPanel root class.
When the best templates are found respective classes must be derived: these extension will be the the implementation classes of the target visual object and they will be instantiated with the org.joty.workstation.gui.Factory methods.
Then in the original source code must be identified for each visual object that makes data access and for its internal components that do so,
- the update-able set of data
- the sql statement used for data presentation (extraction)
In the target code, these two elements find there location in the following statements (for a simple scenario):
- In a simple DataAccessDialog with a simple DataAccessPanel implementation both of the following solutions (or a mix of them) are available:
-
using a call to Factory.addDataAccessPanel like this:
DataAccessPanel dataAccessPanel = Factory.addDataAccessPanel( m_contentPanel, new MyDataAccessPanel(), [updatetable set definition], [query set definition]); - The overriding of the DataAccessDialog.updatableSet() and of the DataAccessDialog.query() methods
or, if the dialog must differenziate its behavior basing on several different modes of opening, the overriding of
the DataAccessDialog.selectiveUpdatableSet() and of the DataAccessDialog.selectiveQuery() methods.
For sample here is a fragment for the implementation of selectiveQuery:
public enum openMode { mode_1, mode_2 } @Override protected String selectiveQuery() { switch ((QueryType) getMode()) { case mode_1: return [one sql select statement]; case mode_2: return [onether sql select statement]; default: return null; } }
-
using a call to Factory.addDataAccessPanel like this:
- In a MultiPanelDialog implementation, instead, calls to Factory.addTab are possible (for each DataAccessPanel implementation) like this :
DataAccessPanel dataAccessPanel = Factory.addTab(m_tabbedPane, new MyDataAccessPane(), [updatetable set definition], [query set definition]); m_tabbedPane.addTab("myPaneNname", null, dataAccessPanel, null); For the main data panel (the first one) the alternative, of using the overrides of the methods above, exists, as in the case of the simple DataAccessDialog. - Within each implementation of the DataAccessPanel class, every org.joty.workstation.gui.Table object may have its associated query defined
as assignment to the org.joty.workstation.gui.Term.m_queryInterface attribute; see this fragment:
Table table = Factory.createTable(this, "MyTermName"); add(table); TableTerm term = tableTerm("MyTermName"); term.m_queryInterface = new QueryInterface() { @Override public String get(GridTerm term) { return [my select statement}; } }; - In the implementation of a org.joty.workstation.gui.CriteriaPanel for a searcher dialog the setQuerySetDef method must be used to specified the sql text for data estraction.
Then the development has to continue obviously with further analysis, from the identification of the keys for the DataAccessPanel implementations and for the org.joty.workstation.gui.Table instances (inner data grids), to the update-ability of the various database fields, from identification of the contexts of data look-up to the cross-referenced links needed among data dialogs and so on: this is only an introduction about the matter.
It is worthwhile here to note that the framework provides the context parameters infrastructure that allows to store values when easy to be caught and to retrieve them when they must be used in various expressions by letting the developer to reduce the traversing of the code for the procurement of the quantity of interest.
It is also to note that any visual data object (data panel or data grid) that wishes to publish its modifications have just to invoke the setAsPublisher method and any visual data object that wishes to be informed of a dialog publishing event, have just to invoke the subscribe method.
The conversion of a Joty application into Accessor mode
The Accessor mode is scoped either to the application object or to each data dialog object.
The Accessor mode at application object scope:
- has its implementation simpler than that one that exists at data dialog scope
- is rarely needed
- is applied inside the framework for the application start up process and as such is a built-in feature of the framework
Because of these reasons, for the application scope the reader is redirected to the source code and related documentation. Here only the transformation of a Joty data dialog into one running in Accessor mode is described, as element constituting the entire conversion process.
Steps for preparing the Accessor class (the precondition)
- Create (if not already existing) the myApp.commonpackage
- Create in it an org.joty.basicAccessor.BasicAccessor derived class. Let's name it 'MyAppAccessor'
- in the 'MyAppAccessor' class implement the overriding of loadDefs() method assuring that it invokes the 'super' implementation.
Steps for setting an org.joty.workstation.gui.DataAccessDialog derived class to the Accessor mode
- place the "m_accessorMode = true;" statement in the constructor.
- add in the body of the MyAppAccessor.loadDefs method an empty template like the following:
m_dialogDataDefs.put(" ", new DialogDataDef() { { m_panelDataDefs.add(new PanelDataDef() { // respect the panel position in the adding sequence { // dataDef section BEGIN ========================================= // A setUpdatableSet("< panel table name >"); // - OR - B setUpdatableSetHolder(new ExprHolder() { public String getExpr() { return null; } public String getSelectiveExpr(String mode) { return null; } }); // A2 setStatementHolder(new ExprHolder() { public String getExpr() { return null; } public String getSelectiveExpr(String mode) { return null; } }); // - OR - B2 (only if dialog is opened with no modes) setStatementSql("< panel Sql text >"); addContextParamName("< a ContextParam name >"); addParamActuator(new ParamActuator() { public String getValue() { return ""; } }); addParamValue("< a param value >"); // dataDef section END ==================================================== m_termDataDefs.put("< term name >", new DataDef() { // for each term that requires .... { // dataDef section (see above) } }); } }); } }); where the verbose literals like "<....>" have clear meaning.
- insert in the template as many "m_panelDataDefs.add(new PanelDataDef() {{...}});" statements as is the quantity of data panels within the dialog, with the respect, in the sequence of statements, of the creation position of each data panel in the dialog constructor. In the case of a searcher dialog, insert one only statement, instead, in the template.
- for each data panel defined in the dialog, or for the only criteria panel of the searcher dialog, take the following steps:
- look for the update-able set definition (do not, obviously, for the searcher dialog) and for the query set definition and put them in
the constructor of the anonymous PanelDataDef (relative to the data panel) through the use of the
statements exemplified in the template above and with the following criteria:
- if the update-able set definition supports several opening mode then use the setUpdatableSetHolder statement else you can use even the setUpdatableSet statement if the definition is simple as a db table name
- if the query set definition support several opening mode then use the setStatementHolder
statement else you can use even the setStatementSql statement, simpler to write but with some more attention to be payed as a draw back.
setStatementHolder usage
- In the implementation of each anonymous ExprHolder derived class, override one or both of the methods available depending of the design of the containing dialog (it might be that dialog supports opening either with open mode specified or without its specification: that case suggests both overrides)
- Remember that the value of the 'mode' parameter of the getSelectiveExpr method is the literalization of the values of the enum type by which is defined the opening mode (in the dialog definition class) so that a sort of conversion is to be done in the typical case construct of the source definition (where the actual enum value was mentioned)
- any invocation to the org.joty.workstation.gui.JotyDialog.contextParameter() method must be replaced with the invocation to org.joty.access.Accessor.paramValue() method
setStatementSql usage
- if in the original definition any invocation of the org.joty.workstation.gui.JotyDialog.contextParameter() method exists the definition can be left as is a part from the substitution of that occurrence with the invocation to org.joty.access.Accessor.paramValue() method, only if the original parameters context received the value for the parameter anciently (in the initialization of the application - typically from configuration context).
- if the scenario is more dynamic or no analysis is desirable about the matter above, you have to modify the definition eliminating the actualization and substituting it (if it does not already exist) with a string substitution token : '%s') and make the setStatementSql invocation be followed by as many invocations of org.joty.access.Accessor.DataDef.addContextParamName method as are the occurrences of '%s' in the new definition of the statement - meaning in the appropriate order.
- the setStatementSql usage is accompanied with two alternatives to the dynamic addContextParamName, with which they can configure a mixed "external" actualization of the various occurrences of '%s':
- org.joty.access.Accessor.DataDef.addParamValue method when you wish to specify a well known value for the parameter
- org.joty.access.Accessor.DataDef.addParamActuator method even more powerful than addContextParamName because it delays not only the evaluation of the parameter value but also let the developer to specify an algorithm to compute it at the time of the its evaluation
-
for each TableTerm object instantiated in the data panel take the following steps:
- put in the anonymous constructor of the PanelDataDef derived class relative to the panel as many "m_termDataDefs.put("< term name >", new DataDef() {{...}});" statements as the quantity of TableTerm objects instantiated in the data panel and having the query set defined.
- look for the update-able set definition and for the query set definition
- Apply to each definition porting the same consideration made above for the data panel
- look for the update-able set definition (do not, obviously, for the searcher dialog) and for the query set definition and put them in
the constructor of the anonymous PanelDataDef (relative to the data panel) through the use of the
statements exemplified in the template above and with the following criteria:
- Remove any method implementation and remove any parameter (or set it to null if not 'optional') that worked for the "old" implementation, now obsolete (see the previous section for an overview of the "now" obsolete implementations).
Steps for converting a data access made at application scope in one running in Accessor mode
- add to the body of MyAppAccessor,loadDefs the following statement template:
m_statementDefs.put(" ", new DataDef() { { setStatementHolder(new ExprHolder() { @Override public String getExpr() { return " "; }; }); } }); - copy the definition of the original statement into the "
" area of the template above - in the new definition replace any actualization of the parameters made originally by ParamContext.contextParameter() invocations with the invocation to org.joty.access.Accessor.paramValue() method
- in the invocation cotext identify the parameters set in the original implementation
- invoke setApplicationScopeAccessorMode() and save the retuned mode
- identify the ParamContext object to be used (the default one is org.joty.workstation.app.Application.m_paramContext
- on this object invoke the setContextParam method for each parameter to be set
- invoke the org.joty.workstation.app.Application.accessorExecute method with the name of the new "stored in the accessot" statement, and with the ParamContext obect specified if different from the default one
- invoke setApplicationScopeAccessorMode("
") - the same as the query statement case a part the invocation of the accessorExecute invocation that is replaced by the org.joty.workstation.app.Application.openAccessorWResultSet method invocation, that returns an already opened WResultSet object to be used for reading data
The case of an executeSql statement
The case of a query statement
Finally, not regarding the conversion process, it is to be noted that in order to get concrete advantage of the accessor mode, the binary of the MyAppAccessor class must be deployed to the server, in the same location where the jar of the Joty server is located. Then the framework must be informed about this location and this is done by setting the remoteAccessor configuration attribute.
As a conclusion it is evident that the conversion process is incremental and can be partial, indeed: only the data access of interest can be converted to the Accessor mode.
The setup of a Joty Mobile application project
Android studio 2.3.3 and later is recommended for the development of a Joty Mobile app.
Create a new Android Application project and in the build.gradle file of the application module add the following lines in the 'dependencies' clause:
Only if Jcenter doesn't exhibit availability of the above artifacts, add the row 'mavenCentral()' (or 'mavenLocal()' - see download page) to the repositories clauses of the build.gradle file of the project.
See OdontiorMobile1App sample for an example of Joty mobile app
The Joty Mobile app as stand alone project or as integration of a Joty Workstation application project
In Joty 2.0 it is typical that the mobile app is just an integration of something reacher that can be the workstation application, since Joty 2.0 Mobile has been developed with the handset devices in mind more than the tablet devices, but this does not deny the chance to developed a completely autonomous mobile project relying on Joty Server.
Either autonomous or integrator of a workstation application, the Joty Mobile app must be developed either basing on the remote accessor mode or not. In the positive case it requires, if not already existing for the workstation application, the existence of an implementation instance of the Accessor class, living/deployed on the Joty Server.
The Joty Mobile app development notes
The development process requires to implement a main activity as subclass of org.joty.mobile.gui.IdleActivity and to implement at least the following methods:
- onCreate
- addMenuItemsToAppMenu
Then for each data entity to be managed the following gui elements must be developed:
- a subclass of the org.joty.mobile.gui.DataMainActivity class with at least the following methods implemented:
- onCreate
- setCollaboratorActivities
- a subclass of the org.joty.mobile.gui.DataResultActivity class with at least the onCreate method implemented.
- a subclass of the org.joty.mobile.gui.DataDetailsActivity class with at least the onCreate method implemented.
- a subclass of the org.joty.mobile.gui.JotyResultFragment class with at least the following methods implemented:
- getKeyFieldName
- createAdapter that must return an instance of JotyResourceCursorAdapter class
- The layout file for the list of the result set and the layout file for the single row of the list
- Graphical resources and the Android Manifest file then complete the minimum requirements
The setup of a Dynamic Java project for an Application Joty Server instance
See the content of the project tree for the Odontior 2.0 sample application.