Open ebruchez opened 11 years ago
As of 2015-01-13, the plan to use Scala.js. This way a single compilation can be used:
This also allows us to master Scala.js, which we want to use more for Form Builder (and later Form Runner).
We are trying to define reasonable chunks of work which lead us somewhere. First goals:
It is ok to hack to get to these goals. The purpose is to get familiar with the tool chain, potential issues, and learn more about what remaining work will be needed.
commons-codec
commons-io
lang3
(#2944)Fetch
API directly XFormsContainingDocument
, model, control tree, control comparator, and relatedElementAnalysis
treesnull
)Immediate concrete next steps:
+1 from evaluator, with a preference for a web app using browser storage, as native apps can be more challenging to deploy.
We as a customer would also +1 that. Just the form runner, right?
@siebertm Correct: this feature is specifically for forms created with Form Builder and running in Form Runner.
This feature will also help us write more responsive UI for Form Builder. We'd like, for example, Form Builder dialogs showing and navigating faster and reducing the number of roundtrips to the server.
The proxy portlet preferences could also benefit.
Hello, Is there any news regarding offline form runner? It is really a requirement from our business people. On the other side how does the Form builder store the form layout. Is it a JSON or XML file? And is the response also an XML JSON file? In which case one would imagine coding a new renderer for mobiles and Flutter can be an option for cross platform compatibility.
@FOC-framework Offline support is still something we'd like to do, but just not actively working at this point in time. Form definitions are stored in an XML format, which essentially looks like HTML + XForms + some Orbeon Forms specific elements and attributes. You can see what it looks like by going, in Form Builder, to Advanced / Edit Source. For services called by the forms, Orbeon Forms supports both XML and JSON.
Moving and reworking the steps into this separate comment:
Goals:
Non-goals:
Steps:
Goals:
DumbXPathDependencies
Non-goals:
Steps:
Goals:
Non-goals:
Steps:
Goals:
PathMap
) supportSteps:
Goals:
Steps:
Goals:
Goal:
Steps:
@ebruchez that's a large chunk of work and i know this is rather far out but if you're at the point you've got an MVP or so to test out, ping me! I really want to try this in our real use cases!
The initial refactoring requires separating the following:
xforms-runtime
and xforms-compiler
XFormsContainingDocument
→ ScalaWe will need the handlers offline to support instantiating new forms offline. Right now, this works as follows:
SAXStore
with the templateSo we need a way to do this when offline as well. We probably need to have SAXStore
and some of the SAX API for this.
Splitting this into modules/projects is not that trivial. We not only have the runtime/compile-time axis, but the "thin client" (what we have now)/full client axis, and the JVM/JS/shared axis.
For example we don't want the "thin client" to pull down the full client. Scala.js prunes the call tree but it's not perfect at doing that, probably, so it's better if we have a clean separation of the "full client" module, which would contain mainly the XForms runtime.
How static state construction works:
XFormsStaticStateImpl.restore
/ .createFromStaticStateBits
/ .createFromDocument
(tests)new PartAnalysisImpl
topLevelPart.analyze()
new RootControl
build()
Client-server communication abstraction:
AjaxClient
must be abstracted or call to a common interface
AjaxEvent
depends on JSClientServer
still extracts information from Element
So for the client-server, we now have:
ClientServerChannel
WireAjaxEvent
For XFormsModelSubmission
:
RegularSubmission
uses Connection
, which uses PropertiesApacheHttpClient
and InternalHttpClient
FetchHttpClient
would be good, although it would have to be async
OfflineHttpClient
, configurable to call back JavaScript functionsSo probably that we don't need to modify much XFormsModelSubmission
. One approach:
Connection
's choice of HttpClient
pluggable
PropertiesApacheHttpClient
and InternalHttpClient
OfflineHttpClient
org.apache.http.client.CookieStore
/Cookie
Another approach is to make Submission
s pluggable, and on JavaScript:
RegularSubmission
, and possibly othersOfflineSubmission
The second approach might be easier as it's not pulling in Connection
.
My 2 cents on this:
when fully offline, we should have an OfflineHttpClient, configurable to call back JavaScript functions
Why not normal fetch
/XHR
which are then caught in a ServiceWorker
? This generates less special cases.
Depending whether this must support IE, of course. But, even we (working with german hospitals) are phasing out IE support...
@siebertm Thanks for the feedback.
Why not normal
fetch
/XHR
which are then caught in aServiceWorker
? This generates less special cases.
The main reason for a JavaScript callback API is embedding in native mobile applications which can then provide their own persistence and service support. It's also very easy to implement on both sides.
For regular online/offline mode in a browser then yes, Fetch support is needed.
Depending whether this must support IE, of course. But, even we (working with german hospitals) are phasing out IE support...
Agreed, and IE support is not a requirement at this point.
For the record, we have now made Connection
implement ConnectionTrait
, with two implementations (JVM/JS). The JS implementation is not done yet.
More work:
CacheableSubmission
depends on XFormsServerSharedInstancesCache
Connection
based on API callbacks and/or FetchWhich parts of the static analysis must not be present in the ElementAnalysis
tree?
SimpleElementAnalysis
ComponentControl.setConcreteBinding
, which uses XBLBindingBuilder
ShadowChildrenBuilder
, which is implemented by ComponentControl
, and uses binding.compactShadowTree
So we should probably separate the "builders": ChildrenBuilderTrait
, ShadowChildrenBuilder
, etc.
So now we are refactoring out all the building of the tree. This will take care of XBLBindingBuilder
and others.
However we need to solve the question of how to pass in the XPath analysis information. We do this after we have built the tree:
rootControlAnalysis.analyzeXPath() // Analyze root control XPath first as nested models might ask for its context
analyzeModelsXPath() // Analyze all models XPath
analyzeControlsXPath() // Analyze controls XPath
For deserialization, the information should be passed to the constructor. So maybe the constructor of the classes should have the XPath analysis information as var
s set to None
, but then the var
s are updated before serialization. Upon deserialization, the proper information can be passed.
Next step is to move towards serialization/deserialization. This includes:
ElementAnalysis
hierarchyScope
Metadata
: must include Mark
, NamespaceMappings
(but no IdGenerator
, XBL index, etc.)We can use case
classes with var
s, or semi-automatic, or manual serialization.
Remaining tasks before we can rebase on the pe branch:
OrbeonClientTest
println
sfreeTransientState
calls/frees everythingOn master (CE) branch:
xformsOffline
formRunnerOffline
P2:
FormRunnerSimpleDataMigrationFunctionLibrary
For 2021.1 this is not a full-fledged feature. Our plan is to enable, possibly optionally, the "Test Offline" feature from Form Builder. This feature allows running a form in test mode using the JavaScript form runtime.
Status
The purpose of this RFE is to gather ideas and track progress of an Orbeon Labs investigation project. The purpose of the project is to make the Orbeon Forms forms engine available on clients, including online and offline web browsers and mobile applications.
As of October 2016, there has been some progress on this project, including:
We expect to continue progress on this project incrementally.
Subprojects, dependencies, and related projects
These are related subprojects
Historical note
With Orbeon Forms 3.7 (back in 2009!), we had an implementation which wasn't bad in concept, but was too limited and based on Google Gears (the precursor to HTML5 local storage among other things). Due to those limitations, Google abandoning Gears and lack of interest from customers at that time, we decided not to maintain it anymore starting Orbeon Forms 3.8. See:
Rationale
The idea is to bring our forms engine to Web apps and "native" mobile apps. This would serve multiple purposes:
The general idea is to make the code which currently runs on the server run on the client, whether within a Web browser directly or as a native application on a mobile device.
We need to abstract and modularize the XForms engine to make it as small as possible and as independent as possible from other things including the servlet API.
The user-interface part would remain browser technology-based. We don't want to change this at all at first and we wants to leverage either an actual Web browser or a Web view within a native app.
One components that we need to have is some kind of abstraction for the client/server communication. Right now that communication is handled via Ajax in the JavaScript code and we have the XForms server on the server. What we would like to do here is allowing the option to have something local like at simple queue. That doesn't seem to be extremely hard to do.
Platforms
General considerations
WKWebView
as of iOS 8Web app
For a web application we have to compile our code to JavaScript. For offline support we can use modern browser APIs.
Native iOS app
The current plan is to use JavaScript as well. In the future, and if it matures and gains the appropriate bindings, Scala Native could become an option as well.
HIstorical considerations
We also considered these options, but have opted not to use them:
Abandoned projects, for reference:
Native Android application
Android already supports Java bytecode. This means we have two options:
We would need to use a WebView probably and then we would need to interact between the application and the WebView. On Android the JavaScript side of a WebView is able to call a Java object that has been exposed.
Modularization effort
The Orbeon code needs to be modularized and abstracted. In particular:
Subsequent steps
Once a prototype is developed, we needs to think about the general architecture of the mobile application, including lifecycle, how to load forms and so on. Form Runner needs to be included, and local storage at least needs to be used.