How to create a custom scope in Quarkus? - cdi

I tried to follow this instruction https://rpestano.wordpress.com/2013/06/30/cdi-custom-scope/
, but it's not working, because the methods of my custom Context are not fired.

You can declare custom scopes in Quarkus. However, Quarkus does not use a full CDI implementation, instead it has a lighter implementation that does not support everything you know from CDI the way you are used to. Reasons are multiple but mostly it is done in order to make it build time friendly.
CDI extensions are one of the things that are inherently runtime based and as such are a bad fit for Quarkus stuff. Instead, you will have to use a Quarkus extension to declare your scope/context. Let me give you some materials for that...
Here is a link to Quarkus CDI guide in general, it lists its limitations and how it compensates for it.
This bit in particular shows how to register a custom scope within extension. The method is as simple as:
#BuildStep
ContextRegistrarBuildItem customContext() {
return new ContextRegistrarBuildItem(new ContextRegistrar() {
public void register(RegistrationContext registrationContext) {
registrationContext.configure(CustomScoped.class).normal().contextClass(MyCustomContext.class).done();
}
});
}
And here is a link to how Narayana Quarkus extension uses this exact same API to register #Transactional. The underlying context class is very similar to what you would use in CDI (or in Weld), take a look at this class that Narayana uses for inspiration.

Related

How to invalidate views for the current session in JSF?

We have an application (Mojarra 2.3) where a user can change a global filter of the data it sees. When that happens, I want to keep the session, but invalidate the active views (which are server side).
I found this question which enables you to count the number of views: How do I count the number of views in a user's JSF session (JSF 2.2)?
Based on that I figured I could remove the attribute in which the views are stored. I came up with this method:
public static void invalidateViews() {
final HttpSession session = Faces.getSession();
List.of("com.sun.faces.application.view.activeViewContexts",
"com.sun.faces.application.view.activeViewMaps",
"com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap",
"org.jboss.weld.context.ConversationContext.conversations")
.forEach(session::removeAttribute);
Faces.redirect(Faces.getRequest().getRequestURL().toString());
}
The com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap was mentioned in the linked question's answer. I kind of guessed that it would not hurt to remove the other attributes. The answer also mentions that it is Mojarra only.
It seems to work so far, but I would like to ask this: should one clear server side views like this? And, if so, how can I support MyFaces as well?
It seems to work so far, but I would like to ask this: should one clear server side views like this?
Given that there is no standard API call for this, this is about the best you can do, yes. I have during the JSF 2.3 work requested for a more specific variant of this functionality to exist in the standard API because I needed to be able to destroy view scoped beans associated with a specific JSF view state (for the OmniFaces view scope unload functionality, see Hacks#removeViewState()). But this has unfortunately not yet been fleshed out because of difficulties with Portlets.
And, if so, how can I support MyFaces as well?
As seen in the OmniFaces Hacks helper class, the session attribute key for MyFaces 2.x is org.apache.myfaces.application.viewstate.ServerSideStateCacheImpl.SERIALIZED_VIEW and 4.x org.apache.myfaces.application.viewstate.StateCacheServerSide.SERIALIZED_VIEW.
By the way,
Faces.redirect(Faces.getRequest().getRequestURL().toString());
this is shorter:
Faces.refreshWithQueryString();

Myfaces CODI DefaultErrorView - examples anywhere?

I've seen a reference to a DefaultErrorView in Myfaces CODI but as usual the
documentation leaves everything to the imagination. I've really found CODI to be a
great JSF addon, but it would benefit such a lot from some examples.
Probably naively I was hoping to be able to catch the dreaded ViewExpiredException
with this code:
#Page(basePath = "/defaultErrorPage.xhtml")
public final class DefaultErrorPage extends DefaultErrorView {
}
...but all that happens after session timeout is that container security takes me
to the login page when I try to issue a get request (clicking on a h:link). Does
anyone know what I can do with this DefaultErrorView, anyone got an example?
Thanks!
In the JavaDoc of DefaultErrorView you see:
...
The class which extends this class will also be used as error-view in case of security violations
(if there is no special error-view configured via
{#link org.apache.myfaces.extensions.cdi.core.api.security.Secured#errorView()})
And in the Wiki you see e.g.:
#Secured
...
In case of a violation CODI will use the DefaultErrorView as navigation target (if configured).
...
and
(Security) Error pages
The following example shows how to create a default error page. It's just allowed to provide one default error page per application.
Instead of implementing ViewConfig it's required to implement the DefaultErrorView interface.
...
as well as the manual usage:
...
this.viewNavigationHandler.navigateTo(DefaultErrorView.class);
...
The Wiki also links a nice example and there you find:
http://code.google.com/a/apache-extras.org/p/myfaces-codi-examples/source/browse/community/src/main/java/org/apache/extras/myfaces/codi/examples/community/view/config/Pages.java
-> everything is fine with the documentation ;-)

#Produces return FacesContext --- why?

I hesitate to ask yet another question on the same topic, but at least now I'm reading, I think, the right docs.
So, this class:
class FacesContextProducer {
#Produces #RequestScoped FacesContext getFacesContext() {
return FacesContext.getCurrentInstance();
}
}
From the weld docs this method does, in fact, apply to Glassfish through: GlassFish is using WELD as the reference implementation for JSR-299: Java Contexts and Dependency Injection for the Java EE platform (CDI).
For the above class, where would it be used? Why do you need a separate class which #Produces a FacesContext?
For the above class, where would it be used? Why is he trying to inject FacesContext?
I think it is done either for
consistency; or
testing.
ad 1. If one tries to do pure CDI, it looks nice when you're not using other dependency lookup mechanisms (as getCurrentInstace() static method). Note that it is really not needed to define a producer and use injection. It is just convenient and consistent with usage of CDI.
ad 2. is explained by blog McDowell links to, just imagine the injection is done with CDI.
Why do you need a separate class which #Produces a FacesContext?
This does not need to be a separate class, you can have single class producing multiple beans. It just helps the clarity of the code to have it separate.
You might want to inject the FacesContext to avoid direct reliance on the static getCurrentInstance() method to make mocking and unit testing simpler.
I've written a bit about that for JSF's own dependency injection mechanisms here.

Suggestion on JSF authorization

I learnt how to use container authentication with JDBC realm.
I searched a lot on internet but I couldn't find anything on JSF authorization except the following article.
JSF authorization
My goal is to avoid access to protected pages using direct links and to show/hide menu items and form components based on the authenticated user privileges.
The last part can be implemented using the rendered attribute of JSF tags but before creating my own dirty and high coupled solution I wonder if there are some specific best practices or libraries that can help. in fact the number of components to be conditionally rendered is quite high and I wouldn't like to write a specific function for each of them.
Perhaps I can create for each authenticated user a map with the names (id) of all the conditionally rendered components and a single function with a String parameter (the unique name/id of the component). Is that a good idea ? What alternatives do I have ?
I wouldn't like to add to the project other general purpose frameworks such as spring for using only a small part of them (the security one).
Thanks
Filippo
With the Expression Language version in Java EE 6 you should be able to use expressions like these:
<h:inputText rendered="#{facesContext.externalContext.isUserInRole('foo')}" />
With older versions, you can create a managed bean of this form:
public class RoleMap implements Map<String, Boolean> {
public Boolean get(Object key) {
ExternalContext extCtxt = FacesContext.getCurrentInstance()
.getExternalContext();
return extCtxt.isUserInRole(key.toString());
}
//TODO: other methods; mostly throwing UnsupportedOperationException
The test can then be expression in the form:
<h:inputText rendered="#{roleMap['foo']}" />
Third party frameworks offer other options, such as the Apache Tomahawk library's visibleOnUserRole component attributes.
Take a look at Apache Shiro, a dedicated security framework (and supposedly erasier to use than Spring Security).

How many ways there are to declare variables in facelets?

I noticed that c:set does not work well used inside "include of include of include", as important notice facelets documentation does't recommend it too.
Now I am using ui:param inside ui:include, but it is a bit dispersive when no attached notes about params comes with the include, is there something other way to declare "global vars"?
This is really a matter of trying to fit old JSP programming into the JSF framework. You should be using backing beans to hold your data.
If you try to hard-code data directly into your xhtml file, you are defeating the purpose of JSF's MVC framework. If you have a specific example of what you are trying to do, I could give you a specific recommendation.

Resources