I have read the following post which was very helpful
Migrating from JSF 1.2 to JSF 2.0
but I am having a problem with the migration as I have a custom view handler which extends from FaceletViewHandler - this is not part of faclets 2.
I am migrating on JBoss 4.2.2 the following:
- JSF 1.2 to JSF 2.0
I also want to migrate the faclets - which i have a problem described above.
In my application, I am also using Tomahawk - is there any problem with this migration?
Thanks in advance.
Elico.
Right, you need to replace FaceletViewHandler by ViewHandlerWrapper.
So the following basic FaceletViewHandler implementation:
import javax.faces.application.ViewHandler;
import com.sun.facelets.FaceletViewHandler;
public class MyViewHandler extends FaceletViewHandler {
public MyViewHandler(ViewHandler parent) {
super(parent);
}
// ...
}
needs to be updated as follows:
import javax.faces.application.ViewHandler;
import javax.faces.application.ViewHandlerWrapper;
public class MyViewHandler extends ViewHandlerWrapper {
private ViewHandler wrapped;
public MyViewHandler(ViewHandler wrapped) {
this.wrapped = wrapped;
}
#Override
public ViewHandler getWrapped() {
return wrapped;
}
// ...
}
I've updated my answer on the migration question accordingly.
To activate MyViewHandler e.g. for JEE7, WEB-INF/faces-config.xml should be defined like:
<?xml version="1.0"?>
<faces-config version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<application>
<view-handler>pkg.MyViewHandler</view-handler>
</application>
</faces-config>
Related
I am trying to use phase Listener in one of my beans in jsf but it's not working.
Class:
package com.mycompany.creditcard1;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.context.FacesContext;
import javax.faces.context.Flash;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named(value = "userDetailsLogin1")
#ViewScoped
public class UserDetailsLogin1 implements Serializable, PhaseListener {
private UserDetails userDetails;
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
#PostConstruct
public void init() {
System.out.println("inti");
userDetails = (UserDetails) flash.get("userDetails");
if (userDetails == null) {
userDetails = new UserDetails();
}
}
public UserDetailsLogin1() {
}
public UserDetails getUserDetails() {
return userDetails;
}
public String action() {
flash.put("userDetails", userDetails);
return "UserDetailsLogin2?faces-redirect=true";
}
#Override
public void afterPhase(PhaseEvent pe) {
System.out.println("after phase");
}
#Override
public void beforePhase(PhaseEvent pe) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}
faces-config file:
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<lifecycle>
<phase-listener>com.mycompany.creditcard1.MyPhaseListener</phase-listener>
</lifecycle>
Error:
Unable to create a new instance of 'com.mycompany.creditcard1.MyPhaseListener': javax.faces.FacesException: com.mycompany.creditcard1.MyPhaseListener
Don't understand why it is showing this?
Any help!!!
Well start by replacing <phase-listener>com.mycompany.creditcard1.MyPhaseListener</phase-listener> by <phase-listener>com.mycompany.creditcard1.UserDetailsLogin1</phase-listener>... you have the wrong class name!
Also, I don't know if it is a good practice to mixup Bean and PhaseListener into the same class...
I am having trouble getting a very basic implementation of a singleton class off the ground with Jersey 2 (2.7) and only Jersey's built-in HK2 dependency injection. I am running this on Tomcat.
My goal is to create a singleton instance of a support class that will be used by various web service methods. I don't have a strong preference between constructor injection, method injection, and annotating a class member (as I do below).
Here is my to-be-singleton class:
package singletest;
import javax.inject.Singleton;
#Singleton
public class JustOne {
private int secretNumber = 0;
public void hitMe(int input) {
secretNumber += input;
}
#Override
public String toString() {
return String.format("{ \"secretNumber\": %s }", secretNumber);
}
}
Here is my application class:
package singletest;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;
#ApplicationPath("/*")
public class MainApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<>();
classes.add(TestResource.class);
return classes;
}
#Override
public Set<Object> getSingletons() {
Set<Object> singletons = new HashSet<>();
singletons.add(new JustOneProvider());
return singletons;
}
}
Here is my Provider/ContextResolver class:
package singletest;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
#Provider
public class JustOneProvider implements ContextResolver<JustOne> {
private static JustOne justOne = new JustOne();
#Override
public JustOne getContext(Class<?> type) {
return justOne;
}
}
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<filter>
<filter-name>singletest.MainApplication</filter-name>
<filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>singletest.MainApplication</param-value>
</init-param>
<!-- pass to next filter if Jersey/App returns 404 -->
<init-param>
<param-name>jersey.config.servlet.filter.forwardOn404</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>singletest.MainApplication</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
The resource where I intend to inject the singleton instance of my JustOne class:
package singletest;
import javax.inject.Inject;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("/test")
public class TestResource {
#Inject
private JustOne justOne;
#GET
#Consumes(MediaType.TEXT_PLAIN)
#Produces(MediaType.APPLICATION_JSON)
#Path("/func1/{input}")
public Response func1(#PathParam("input") int input) {
justOne.hitMe(input);
String responseData = justOne.toString();
return Response.ok(responseData).build();
}
}
This warning is raised when the war is deployed/initialized in Jersey:
Apr 28, 2014 11:48:25 AM org.glassfish.jersey.server.ApplicationHandler initialize
INFO: Initiating Jersey application, version Jersey: 2.7 ${buildNumber}...
Apr 28, 2014 11:48:25 AM org.glassfish.jersey.internal.inject.Providers checkProviderRuntime
WARNING: A provider java.lang.Class registered in SERVER runtime does not implement any provider interfaces applicable in the SERVER runtime. Due to constraint configuration problems the provider java.lang.Class will be ignored.
And the error I get when I call this web service:
type Exception report
message A MultiException has 3 exceptions. They are:
description The server encountered an internal error that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: A MultiException has 3 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=JustOne,parent=TestResource,qualifiers={}),position=-1,optional=false,self=false,unqualified=null,58952407)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of singletest.TestResource errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on singletest.TestResource
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:333)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
So, I get it: hk2 isn't getting enough information to create/bind a JustOne instance and/or find/use my JustOneProvider. I'm sure I'm missing something basic. Any guidance would be appreciated.
bind(JustOne.class).to(JustOne.class).in(Singleton.class);
is the most important part. Without "in(Singleton.class)" multiple instances of JustOne will be created.
Okay, after spending a very healthy chunk of time on this, I got it working.
I used an HK2 AbstractBinder and JAX-RS Feature (javax.ws.rs.core.Feature).
It turned out that no Provider/ContextResolver was required.
Application:
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;
#ApplicationPath("/*")
public class MainApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<>();
classes.add(TestResource.class);
classes.add(JustOneFeature.class);
return classes;
}
}
To-be-singleton class:
public class JustOne {
private int secretNumber = 0;
public int getSecretNumber() {
return secretNumber;
}
public void bumpSecretNumber() {
secretNumber += 1;
}
}
Binder:
import org.glassfish.hk2.utilities.binding.AbstractBinder;
public class JustOneBinder extends AbstractBinder {
#Override
protected void configure() {
bind(new JustOne()).to(JustOne.class);
}
}
Feature:
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
public class JustOneFeature implements Feature {
#Override
public boolean configure(final FeatureContext context) {
context.register(new JustOneBinder());
return true;
}
}
Resource that gets singleton injected:
import javax.inject.Inject;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("/test")
public class TestResource {
#Inject
private JustOne justOne;
#GET
#Consumes(MediaType.TEXT_PLAIN)
#Produces(MediaType.APPLICATION_JSON)
#Path("/func1/{input}")
public Response func1(#PathParam("input") int input) {
justOne.bumpSecretNumber();
String responseData = String.format("{ \"result\": %s }", input + justOne.getSecretNumber());
return Response.ok(responseData).build();
}
}
As soon as I define a composite component in a .taglib.xml to have a <handler-class>, the .xhtml file is ignored.
What I need is a xhtml/facelet based component with a component-type (UIComponent-derived class) and(!) also with a taghandler class. My aim is to catch all working on its child tags in order to be able to activate a custom cdi scope during this.
I found a way by looking at the richfaces impl.jar.
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
<factory>
<tag-handler-delegate-factory>de.sundn.regionscoped.jsf.BehaviorsTagHandlerDelegateFactoryImpl</tag-handler-delegate-factory>
</factory>
</faces-config>
Implement the factory
package de.sundn.regionscoped.jsf;
import javax.faces.FacesWrapper;
import javax.faces.view.facelets.BehaviorHandler;
import javax.faces.view.facelets.ComponentHandler;
import javax.faces.view.facelets.ConverterHandler;
import javax.faces.view.facelets.TagHandlerDelegate;
import javax.faces.view.facelets.TagHandlerDelegateFactory;
import javax.faces.view.facelets.ValidatorHandler;
/**
* #author Nick Belaevski
*/
public class BehaviorsTagHandlerDelegateFactoryImpl extends TagHandlerDelegateFactory implements
FacesWrapper<TagHandlerDelegateFactory> {
private TagHandlerDelegateFactory factory;
public BehaviorsTagHandlerDelegateFactoryImpl(TagHandlerDelegateFactory factory) {
this.factory = factory;
}
#Override
public TagHandlerDelegate createBehaviorHandlerDelegate(BehaviorHandler owner) {
return factory.createBehaviorHandlerDelegate(owner);
}
#Override
public TagHandlerDelegate createComponentHandlerDelegate(ComponentHandler owner) {
// TagHandlers structure is created when view is compiled
// so there's no need to check for BehaviorsStack
if (owner instanceof BehaviorsAddingComponentHandlerWrapper) {
// this is to avoid StackOverflowError because of ComponentHandler constructor call
return null;
}
ComponentHandler wrappedHandler = new BehaviorsAddingComponentHandlerWrapper(owner);
return factory.createComponentHandlerDelegate(wrappedHandler);
}
#Override
public TagHandlerDelegate createConverterHandlerDelegate(ConverterHandler owner) {
return factory.createConverterHandlerDelegate(owner);
}
#Override
public TagHandlerDelegate createValidatorHandlerDelegate(ValidatorHandler owner) {
return factory.createValidatorHandlerDelegate(owner);
}
#Override
public TagHandlerDelegateFactory getWrapped() {
return factory;
}
}
PF 3.5.10, Mojarra 2.1.21, omnifaces 1.5
I have a JSF library (with css files only). This library is in a .jar file. The css will be included in xhtml with
<h:outputStylesheet library="mylib" name="css/mycss.css">.
In html it is rendered to the following: localhost:8080/cms/javax.faces.resource/css/mycss.css.jsf?ln=mylib
CSS file of primefaces is rendered to:
localhost:8080/cms/javax.faces.resource/primefaces.js.jsf?ln=primefaces&v=3.5.10
Notice the library version (&3.5.10) at the end. How can I do the same thing ? Should I write version in Manifest.mf. Or how can I use jsf-versioning in jar file?
That's unfortunately not possible. Library versioning is not supported for resources in JAR.
You've basically 2 options:
Do it the easy and ugly way, include server's startup time as query string. Given that you're using OmniFaces, you could use its builtin #{startup} managed bean referring a java.util.Date instance in application scope:
<h:outputStylesheet ... name="some.css?#{startup.time}" />
<h:outputScript ... name="some.js?#{startup.time}" />
Or perhaps you've the version already as some application variable.
<h:outputStylesheet ... name="some.css?v=#{app.version}" />
<h:outputScript ... name="some.js?v=#{app.version}" />
Update: Notwithstanding, this doesn't work for <h:outputStylesheet>. See also: https://github.com/javaserverfaces/mojarra/issues/3945 or https://github.com/javaee/javaserverfaces-spec/issues/1395
It works for <h:outputScript> though, which had a very simliar bug report which was implemented pretty soon https://github.com/javaserverfaces/mojarra/issues/1216
Do the same as PrimeFaces, create a custom ResourceHandler.
public class MyVersionResourceHandler extends ResourceHandlerWrapper {
private ResourceHandler wrapped;
public MyVersionResourceHandler(ResourceHandler wrapped) {
this.wrapped = wrapped;
}
#Override
public Resource createResource(String resourceName) {
return createResource(resourceName, null, null);
}
#Override
public Resource createResource(String resourceName, String libraryName) {
return createResource(resourceName, libraryName, null);
}
#Override
public Resource createResource(String resourceName, String libraryName, String contentType) {
final Resource resource = super.createResource(resourceName, libraryName, contentType);
if (resource == null) {
return null;
}
return new ResourceWrapper() {
#Override
public String getRequestPath() {
return super.getRequestPath() + "&v=1.0";
}
#Override // Necessary because this is missing in ResourceWrapper (will be fixed in JSF 2.2).
public String getResourceName() {
return resource.getResourceName();
}
#Override // Necessary because this is missing in ResourceWrapper (will be fixed in JSF 2.2).
public String getLibraryName() {
return resource.getLibraryName();
}
#Override // Necessary because this is missing in ResourceWrapper (will be fixed in JSF 2.2).
public String getContentType() {
return resource.getContentType();
}
#Override
public Resource getWrapped() {
return resource;
}
};
}
#Override
public ResourceHandler getWrapped() {
return wrapped;
}
}
Or if you happen to already use OmniFaces, it could be done simpler:
public class YourVersionResourceHandler extends DefaultResourceHandler {
public YourVersionResourceHandler(ResourceHandler wrapped) {
super(wrapped);
}
#Override
public Resource decorateResource(Resource resource) {
if (resource == null || !"mylib".equals(resource.getLibraryName())) {
return resource;
}
return new RemappedResource(resource, resource.getRequestPath() + "&v=1.0");
}
}
Either way, to get it to run, register it as <resource-handler> in /META-INF/faces-config.xml of the JAR.
<application>
<resource-handler>com.example.MyVersionResourceHandler</resource-handler>
</application>
You can also use your project version and append it as a version number for your resource files. This can be done using the maven-war-plugin. The maven-war-plugin will look at your pages during the build time and replace the defined properties.
The following example shows you how to configure the maven-war-plugin to filter your webapp resources in order to inject the custom property asset.version:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
...
<properties>
<asset.version>${project.version}</asset.version>
</properties>
...
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>gif</nonFilteredFileExtension>
<nonFilteredFileExtension>ico</nonFilteredFileExtension>
<nonFilteredFileExtension>jpg</nonFilteredFileExtension>
<nonFilteredFileExtension>png</nonFilteredFileExtension>
<nonFilteredFileExtension>pdf</nonFilteredFileExtension>
</nonFilteredFileExtensions>
<failOnMissingWebXml>false</failOnMissingWebXml>
<webResources>
<webResource>
<directory>${basedir}/src/main/webapp</directory>
<filtering>true</filtering>
</webResource>
</webResources>
</configuration>
</plugin>
...
</plugins>
</build>
</project>
The asset.version property can then be used in your JSF file.
Here is an example tested with JSF 2.2:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html ...
xmlns:jsf="http://xmlns.jcp.org/jsf">
...
<script jsf:name="js/libs/pure/pure-min.css?v=${project.version}" />
The result (in my case) will be the following:
<script type="text/javascript" src="/context-path/javax.faces.resource/js/libs/pure/pure-min.css.xhtml?v=1.0.15-SNAPSHOT"></script>
#Balusc response said "well, not a bug, but oversight and spec fail". It seems like css resources deployed in libraries cannot be versioned with mojarra 2.2.14. Is it right? I tried to implement your solution with a custom ResourceHandler, but resource returned by getWrapped().createResource(resourceName, libraryName) always returns null. It seems like createResource() try to find the library's resources (like css/layout.css) with path /META-INF/resources/ but it lacks the version.
To workaround the problem i have overrided createResource method on a custom ResourceHandler which extends Omnifaces DefaultResourceHandler to add version prefix to the resourceName
#Override
public Resource createResource(String resourceName, String libraryName) {
if (libraryName != null && libraryName.equals(LIBRARY_NAME)) {
if (!resourceName.startsWith(version)) {
resourceName = version + "/"+resourceName;
}
}
return super.createResource(resourceName, libraryName);
}
With this workaround the generated link looks like
<link type="text/css" rel="stylesheet" href="/javax.faces.resource/1_0_3/css/layout.css?ln=common&v=1_0_3"/>
for the outputStylesheet declaration
<h:outputStylesheet library="common" name="css/layout.css" />
I'm not sure this is the best workaround.
Interception with CDI works perfectly in #Named , but doesn't in #ManagedBean:
Logable.java
#InterceptorBinding
#Retention(RUNTIME)
#Target({TYPE, METHOD})
public #interface Logable {
}
LoggingInterceptor.java
#Logable
#Interceptor
public class LoggingInterceptor {
#AroundInvoke
public Object log(InvocationContext ctx) throws Exception {
//log smth. with ctx.
}
}
WorkingBean.java
#Named
#Logable
public class WorkingBean implements Serializable {
//works : methods will be logged
}
beans.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<interceptors>
<class>LoggingInterceptor</class>
</interceptors>
</beans>
ViewScopedBean.java
#Logable
#ManagedBean
public class ViewScopedBean implements Serializable {
//doesn't work
}
I'm aware, that this kind of Interceptor is meant to work with WebBeans (and EJB),
but i'm searching for solution for both worlds (described + JSF) with same Interceptor concept
I need #ViewScoped #ManagedBean, thats why i cant get rid of #ManagedBean in favour of pure WebBeans
System:
Mojarra 2.1.7
Primefaces 3.2
As far as I understand, there isn't one. JSF doesn't have anything supporting interception.
JSF does not support the CDI interception like you have posted per se. A CDI interceptor will work for lifecycle methods like #PostConstruct
#Inherited
#InterceptorBinding
#Retention(RUNTIME)
#Target({TYPE})
public #interface TypeLogger {
#Nonbinding
public LoggingLevel logLevel() default LoggingLevel.INFO;
}
Here is how it would be used since it only binds to the #Target({TYPE})
#ManagedBean
#ViewScoped
#TypeLogger
public class Index implements Serializable {
private static final long serialVersionUID = 3336392241545517919L;
#PostConstruct
private void init() {
setup();
}
}