nine years ago i implemented ExtValMessageInterpolatorAdapter. back then it allowed to combine the MessageInterpolator (bv) and the MessageResolver (extval). with that it was easy to load violation-messages from a custom message-source. it was needed because there was no agreement in the eg about it. from my first presentation about bv (in 2009) until now i always hear the same (valid) feedback (that there is a gap). the result (back then) was BVAL-217, but besides that nothing changed. four years ago there was the last (official) extval-release. the main reason was that most projects limited themselves to std. bv, because jsf as well as some component libs filled the most important gaps. years later there are still extval features which aren't part of the spec. (message-resolving is just one of them). as a "replacement" projects drop the corresponding requirement/s, use weird workarounds, "copy" parts of frameworks like extval or they moved away from bv and/or jsf anyway.
recently i was asked if it is possible to load bv-violation-messages from a database. furthermore, it would be beneficial to re-use custom concepts for type-safe messages. in such cases apache codi and later on deltaspike helped a lot to benefit from (or implement) such features easily. however, adding such frameworks isn't always an option (although they would help a lot) and in some cases there are still some limits.
so i extracted some parts from extval, codi and deltaspike and combined it with new ideas.
without type-safe messages available with deltaspike, i usually use something like the following pragmatic approach for type-safe messages:
that's easy to use, refactor and it's even possible to create an extension which autom. detects all enums implementing that interface and check for message-id clashes. however, when it comes to bean-validation we have the issue that we can't reference the message-id in a type-safe manner (due to the limited capability of java-annotations in combination with the fact that bv specifies that the message-attribute of constraint-annotations needs to be a string).
to allow at least one enum-type per bv-constraint we can benefit from the composite-constraint feature which is available since v1.0. with that we can define e.g.:
furthermore, in some cases it's useful to use information about the property in the violation message. in the listing above it's realized with the constraint-attribute propertyLabel. with std. bv you can hardcode that info. the main issue here is that there is no i18n support for the constraint-attribute value. instead of (manually) post-processing the violation-messages, it would be better to use the std. key-syntax to reference a different value in the message-source.
to summarize it, we would like e.g. to store the violation-text:
The length of '{propertyLabel}' should be between '{min}' and '{max}'
in a database, create a custom enum which implements a custom interface like MessageId and optionally (type-safe) labels which support i18n (the label-texts are stored in message-sources as well).
for the property-label we also create the corresponding entries in the database.
using those parts with @Length would e.g. look like:
and the resulting message is e.g.:
The length of 'Surname' should be between '2' and '50'
the propertyLabel attribute can be a string following the std. key-format to support i18n.
alternatively it can be also a custom enum (implementing a custom interface). it isn't the same, but similar to the type-safe message-enum itself. due to the autom. interpolation the label-enum needs to be slightly different - e.g.:
the (custom) LabelId interface is just used to distinguish labels from the message itself. since the label is a constraint-attribute it gets interpolated by bv itself and therefore we need to force the key-format to identify the parts which need to be resolved in an own step.
to realize all that you just need to add the ds-bv-label-addon e.g. by adding https://rawgit.com/os890/ds-bv-label-addon/public as maven-repository and afterwards the maven-dependency as well as the custom message-interpolator:
to resolve violation-messages e.g. from a database you can add one or more beans like:
if you like to use message- and/or label-enums you can implement one or more beans like:
the git-repository illustrates different use-cases including one which shows how to share one constraint between different modules without using a shared message-enum (but still keep the type-safe approach) by using a shared composite-constraint in combination with a composite-constraint per module (which delegate to the shared composite-constraint).
Friday, June 22, 2018
Sunday, June 10, 2018
[add-on] no flush with org.apache.deltaspike.jpa.api.transaction.Transactional #readOnly and hibernate
jpa supports FlushModeType COMMIT and AUTO. for some use-cases that isn't enough. in case of org.apache.deltaspike.jpa.api.transaction.Transactional#readOnly(true) you will get a #rollback instead of a #commit at the end of the transaction. however, with some other frameworks you can get special behavior. e.g. some use org.hibernate.FlushMode#MANUAL once they detect hibernate as the jpa-provider. deltaspike only provides portable features and therefore you won't get such a special behavior out-of-the-box. however, deltaspike provides a rich set of extension-points. with a custom org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy it's a matter of less than 100 loc to integrate org.hibernate.FlushMode#MANUAL as mentioned above. you can find a corresponding prototype here.
Saturday, May 26, 2018
[add-on] javax.annotation.security.* with deltaspike
intro/background:
recently DELTASPIKE-1345 was reported. since i checked the available integration of javax.annotation.security.* as well as JSR-375 just recently, it was clear that there isn't a well-established CDI extension which integrates with the servlet- and ejb-api (at least at this point).
in the past few years we usually used @Secured (or @Secures) to integrate with those and other authentication (and authorization) mechanisms. in most cases that allowed a type-safe and more CDI-like approach in combination with solid security-frameworks like http://shiro.apache.org
however, (currently) projects like keycloak are integrated e.g. with wildfly (and therefore with javax.annotation.security.*), but only for servlet based artifacts and EJBs.
since JSR-375 is integrated with CDI out-of-the-box, only EE6 and EE7 still have a gap in view of those annotations for authentication (in combination with CDI). in most cases it's enough to use @Secures in combination with the std. EE-APIs (like it's illustrated for JSF in one of the wildfly-demos). however, it's for sure inconsistent that those annotations can be used with different EE-APIs, but out-of-the-box not with CDI beans. therefore, i prototyped https://github.com/os890/ds-role-bridge-addon
it's a bridge which supports @DenyAll, @PermitAll, @RolesAllowed and @RunAs. i skipped the support for @DeclareRoles in combination with @RunAs, because a full support with EJBs wouldn't be portable anyway. the remaining annotations are also integrated with EJBs and therefore in most cases it should just work as it would be supported out-of-the-box.
the short story:
as shown in the demo-applications it's just needed to add the bridge as a runtime-dependency and use the javax.annotation.security.* annotations directly at the CDI beans. behind the scenes the final-role check is delegated to the servlet-api or if it isn't available (or there is no active servlet-request), a fallback gets triggered which delegates the check to the EJBContext. only @RunAs required a custom role-evaluation (including an explicit approach for the integration with EJBs).
the result:
https://github.com/os890/ds-role-bridge-addon should allow the same overall usage of @DenyAll, @PermitAll, @RolesAllowed and @RunAs (please report an issue if there is a difference). the main (known) difference is that you need to use annotations like @RolesAllowed explicitly (there is no "default/implicit" protection). furthermore, the result of a violation is a java.lang.SecurityException. however, the bridge also provides a rich set of SPIs which allows to customize the default behavior (in this case e.g. with an @Alternative implementation of AccessDeniedHandler).
btw. since cdi is really powerful it took longer to create the examples then the bridge itself.
recently DELTASPIKE-1345 was reported. since i checked the available integration of javax.annotation.security.* as well as JSR-375 just recently, it was clear that there isn't a well-established CDI extension which integrates with the servlet- and ejb-api (at least at this point).
in the past few years we usually used @Secured (or @Secures) to integrate with those and other authentication (and authorization) mechanisms. in most cases that allowed a type-safe and more CDI-like approach in combination with solid security-frameworks like http://shiro.apache.org
however, (currently) projects like keycloak are integrated e.g. with wildfly (and therefore with javax.annotation.security.*), but only for servlet based artifacts and EJBs.
since JSR-375 is integrated with CDI out-of-the-box, only EE6 and EE7 still have a gap in view of those annotations for authentication (in combination with CDI). in most cases it's enough to use @Secures in combination with the std. EE-APIs (like it's illustrated for JSF in one of the wildfly-demos). however, it's for sure inconsistent that those annotations can be used with different EE-APIs, but out-of-the-box not with CDI beans. therefore, i prototyped https://github.com/os890/ds-role-bridge-addon
it's a bridge which supports @DenyAll, @PermitAll, @RolesAllowed and @RunAs. i skipped the support for @DeclareRoles in combination with @RunAs, because a full support with EJBs wouldn't be portable anyway. the remaining annotations are also integrated with EJBs and therefore in most cases it should just work as it would be supported out-of-the-box.
the short story:
as shown in the demo-applications it's just needed to add the bridge as a runtime-dependency and use the javax.annotation.security.* annotations directly at the CDI beans. behind the scenes the final-role check is delegated to the servlet-api or if it isn't available (or there is no active servlet-request), a fallback gets triggered which delegates the check to the EJBContext. only @RunAs required a custom role-evaluation (including an explicit approach for the integration with EJBs).
the result:
https://github.com/os890/ds-role-bridge-addon should allow the same overall usage of @DenyAll, @PermitAll, @RolesAllowed and @RunAs (please report an issue if there is a difference). the main (known) difference is that you need to use annotations like @RolesAllowed explicitly (there is no "default/implicit" protection). furthermore, the result of a violation is a java.lang.SecurityException. however, the bridge also provides a rich set of SPIs which allows to customize the default behavior (in this case e.g. with an @Alternative implementation of AccessDeniedHandler).
btw. since cdi is really powerful it took longer to create the examples then the bridge itself.
Friday, March 30, 2018
multi-profiles in one minute
2012 spring added bean-profiles which is similar to project-stages added in myfaces-codi 2010. deltaspike improved and unified the project-stage concept. for the average case it's (imo) easier to handle than bean-profiles. however, from time to time users come up with some very special edge-cases which can be done with (custom) expressions supported by @Exclude. per definition such cases can get quite complex and usually there is an easier approach with deltaspike. in all the years (on the mailing-lists and in projects) i just saw one case which would really benefit a bit from the (imo) more complex bean-profiles approach. even in that case the result wasn't just "bad luck" and a questionable workaround as a result. instead it is possible to implements bean-profiles as a deltaspike-addon with less than 30 lines of code.
the usage is quite simple.
a type-safe approach based on cdi-stereotypes is supported as well. the usage of the type-safe approach is also straightforward: enabling 1-n profiles can be done with any active config-source.
the implementation including tests are available at ds-multi-profile-addon.
the usage is quite simple.
a type-safe approach based on cdi-stereotypes is supported as well. the usage of the type-safe approach is also straightforward: enabling 1-n profiles can be done with any active config-source.
the implementation including tests are available at ds-multi-profile-addon.
Subscribe to:
Posts (Atom)