Hi Emmanuele,
Thanks for the proposal review and comments.
First and foremost, let me stress out the proposal is to create a branch, 4.0.x.
Since there are several topics that of course need to be discussed and agreed
upon, all this work would serve as a concrete platform to do that, with as much
proof as possible that everything keeps working.
Not to merge or force any of this in the current 3.x series.
Follow up inline.
Dear Gabriel,
I went through your proposal; I will start with some comments about the motivation section:
- The persistence abstractions are powered by Google’s Generic DAO Framework, which is not maintained since years ago
- This refactoring was already completed and working, as reported in this issue:
- JDK11 compatibility #128 [1]
Oh that’s interesting. Unfortunately I couldn’t know, or at least it was easy to oversight,
since that issue is three years old, it’s not merged, and the title does not relate to the persistence
framework; though the description does indeed mention it. Should I’ve noticed it, it would have
saved me a ton of work.
- All the GenericDAO constructs were ported to Hibernate’s criteria and to some newly created classes to reduce the impact on the existing code as much as possible.
Yes, the Hibernate criteria API also makes sense.
Personally, I prefer QueryDSL for the type-safety part. QueryDSL code-generates classes that
let you create arbitrary queries in a type safe way, and adds no runtime dependencies, just a
compile-time @Entity annotation processor.
In any case this and everything else is up to discussion.
- The REST APIs exposed by GeoFence’s standalone server application, and the GeoFence embedded engine in GeoServer, have some differences, which makes it hard to use a REST client interchangeably.
- When the REST APIs were reimplemented in the embedded configuration (in the geofence-server module), they did not follow the detailed documentation available at GeoFence REST API [2] , that was followed in the initial (standalone) implementation. I would not create a third API, but would stick to the existing one: breaking backwards compatibility is something we try very hard not to do in GeoServer, since there are deployed systems depending on it that would break on upgrade.
As much as I very much agree with the principle, we’re kind of in an impossible situation here.
I agree having two disparate REST APIs is bad enough.
On the other hand, I have been working for a year now on a system that needs to interface with GeoFence.
I would rather have the chance to deploy GeoFence standalone or embedded, and be able to use the same
REST API regardless, but that’s impossible without tons of hacks.
It’s also difficult to implement a client even if you choose one of them, since there are some inconsistencies like
requests to create a Rule accepting a given content type (e.g. application/json) but returning text/plain with the
rule id, and then expecting long to fetch the rule.
Additionally, in order to replace Spring RMI with an API client, the client would need to implement GeoFence standalone’s
REST API, but a client working against GeoServer would implement GeoFence embeeded’s REST API, so we’re just multiplying
the maintenance problem.
So my proposal is to:
1- use an API-first approach through an OpenAPI specification that’s common to both kinds of deployments.
2- Maintain the current embedded API for as long as necessary in GeoServer.
3- Also expose the new API as v2, where anyone can use the provided or generate ready to use client libraries in different programming languages
(I’ve actually just finished porting both geoserver plugins, will send a link once I get the configuration part working too in a backward compatible way)
Thinking of an upgrade path:
For GeoServer embedded, REST API wise, wouldn’t make any difference, other than v2 also being available, or not even, could be a configuration choice.
For standalone, an upgrade would also mean a standalone GeoFence upgrade, so it doesn’t matter if it uses RMI or the new OpenAPI interface to communicate with GeoFence
Regarding the other points, it’s great getting rid of the older libraries (we had to revive the old Hibernate Spatial in order to keep up with the JTS upgrades – see https://github.com/geosolutions-it/hibernate-spatial).
So, apart from the notes above, I’m good with the various motivations and points in the proposal, because they aim to get rid of older unmaintained libraries and to keep the libs aligned with the ones used in GeoServer.
nice!
That said, I’m quite concerned with the modules refactoring:
- They are not strictly needed and motivated by the previous points.
While I disagree (again, for a longer term, on 4.x) , I see my mistake in not emphasizing
on the motivation section and only mentioning sharing the maintenance burden in the
overview section, I guess I just didn’t want to come across as arrogant or patronizing.
Since we’re kicking off the discussion, allow me to elaborate:
I know both Alessio and yourself shall know the codebase from the heart, and that’s great,
but bear with me, as an outsider and newcomer to the project, I had a
rather hard time getting acquainted with it, hence my intention is to make sure the architecture
is very clear and upfront, not only for us but for any other potential collaborators. Something
closer to a Screaming Architecture, as my initial struggles were related to figuring out the architecture,
and how components relate to each other, not from the persistence viewpoint but from
the business domain view.
If you look at the following comparison of 3.x and 4.x proposed modularity, I think the 3.x one doesn’t
say much about what the software system is or does, but instead I see there are apis, persistence, and
a gui.
The 4.x proposal on the other hand makes it very clear that the business domain has 4 domain units
and a common object model, and that’s all one would need to look into to understand GeoFence.
No Spring, no JPA, no REST, no anything else than pure domain specific logic.
Everything else is integration and implementation detail you can dig into if need be.
- They will likely make it difficult to review and functionally validate.
They might. Hence all functional tests are in the domain modules themselves, without requiring digging
into integration details, while at the same time serve as base integration tests for both the persistence
and client api integrations.
The tests (e.g. the most important being RuleReaderServiceImplTest) run against in-memory
persistence abstraction implementations that use RuleFilter itself as predicate, through the
new RuleFilter.matches(Rule):boolean method, and that helped me a lot to make sure both the openapi
client and JPA backed Repositories do the right thing and are hence interchangeable as backing
Repositories for the different services.
Other things like making the object model immutable also helps to clearly reason about things, like in
avoiding side effects with argument objects being changed by functions.
- They may introduce further issues, along with the potential ones caused by the already big library upgrade shock.
Yes they would, as there’s no such thing as bug-free software is it? On the bright side we will be taking on the burden of stress
testing and fixing for our current customer, and another one in the very near future.
- They may be a blocker for the current maintainers to keep up the work and to respond quickly to the issues that will pop up, especially in the first times it will be released.
Indeed. So once again, no rush. I’m only asking for a branch so we have a common place to review, discuss, and
coordinate on things. I honestly think having this starting point is much better than trying to make one proposal at a time
because it’s practically impossible, at least for me, to foresee all these changes, optimizations, or whatever in advance.
If we don’t take the opportunity to refactor and improve while we have the funding, we might as well end up in endless
discussions and consume all those precious resources without anything concrete as outcome.
My proposal is to split the current proposed work in two phases:
- A first GSIP (and PR) focused on the points listed in the motivations/proposal, that is an upgrade of the libraries, and partial rewriting of the code/configurations strictly needed to make the new libs work. That GSIP would be reviewed, tested, and accepted quite quickly, because this is a much-needed improvement with a well-defined scope, and the current maintainer would know the existing dependencies between modules.
That’s not a bad idea at all, thinking of the 3.x series. I can explore it but definitely need
to reach a compromise to:
- ditch the GWT gui and provide only a spring-boot application for the current (standalone) REST API. Or maybe
not even, does anyone use it? or does everyone uses the embedded engine?
- keep on using RMI for GeoServer to GeoFence communication
- A second GSIP about the module refactoring, that IMHO should be agreed upon by the developers’ community (and in particular module maintainers) in advance, to explore the possible alternative design, and find one that both parties agree upon. It would need more time to be investigated, tested, discussed, and in the end adopted and would give time to the other devs to get accustomed to it.
That would be this one. Given I’m committed to it I’d rather get the go ahead to have a 4.x branch or be forced to work on it from my fork alone.
Thanks again for the review and comments, looking forward to yours and anyone else’s.
Cheers,
Gabe.
Looking forward in reading your feedback.
Cheers,
Emanuele
[1] https://github.com/geoserver/geofence/issues/128
[2] https://github.com/geoserver/geofence/wiki/GeoFence-REST-API
Hi list,
I’ve just created a GSIP (216) with a proposal to make several improvements to GeoFence.
Please see https://github.com/geoserver/geoserver/wiki/GSIP-216 for details.
camptocamp
INNOVATIVE SOLUTIONS
BY OPEN SOURCE EXPERTS
Gabriel Roldán
Geospatial Developer