voyent
PushRenderer IceFaces  XML
Forum Index -> ICEpush General
Author Message
JackJack

Joined: 05/Sep/2014 07:44:24
Messages: 3
Offline


I am trying to implement an IceFaces Project where I have a java web service doing push-notifications.

I have a client that logs in and sends a push notification through the web service to others.

My problem is that I discovered that I have to use portableRenderer() because the web service is outside the JSF context. It needs a ServletContext as argument.

I tried to do it but it seems to have problem in passing the context from client to web service because ServletContext is not an available type (integer, string, boolean, ...).

The error returned is NullPointerException. Any suggestion?

I have tried to follow some guides on internet and PushRenderer() locally works good.
deryk.sinotte


Joined: 26/Oct/2004 00:00:00
Messages: 1008
Offline


Perhaps a bit more information about your environment and what you are trying to do:

What version of ICEfaces are you running?

Can you post the stack trace for the NullPointerException?

You are correct that if you are trying to do a Push from outside a JSF request, you'll need to get a reference to a PortableRenderer and use that. You should get the initial PortableRenderer reference during a request that does have access to either the FacesContext or an HttpSession so that the PortableRenderer can get the internal references that it needs and save the PushContext properly.

Can you post the snippets of code in your application where you are creating the PortableRenderer and the area of your application where the web service is calling back into your application to use the PortableRenderer?

Deryk Sinotte
Team Lead
ICEsoft Technologies, Inc.
JackJack

Joined: 05/Sep/2014 07:44:24
Messages: 3
Offline


I'm using Eclipse 4.3 Kepler and ICEFaces 3.3.0.

In my project there are two types of users: Clients and Managers. Every manager can be associated with one or more clients while each client can be associated with only one manager.

What I'm trying to do is to notify the corrispondent manager every time one of his clients logins. Unfortunately, the notification can not be made directly by the client but by a Web Service. The Web Service is a SOAP Web Service and was created following the wizard of Eclipse.

Below I place the stack trace.

************************* STACK TRACE *************************

Code:
set 08, 2014 2:14:10 PM org.icefaces.impl.renderkit.DOMRenderKit <clinit>
 Informazioni: 
 ICEsoft Technologies Inc.
 ICEfaces 3.3.0
 Build number: 11
 Build date: 130416
 Revision: 34423
 
 set 08, 2014 2:14:11 PM org.apache.axis.utils.JavaUtils isAttachmentSupported
 Avvertenza: Unable to find required classes (javax.activation.DataHandler and javax.mail.internet.MimeMultipart). Attachment support is disabled.
 set 08, 2014 2:14:12 PM org.apache.catalina.startup.TaglibUriRule body
 Informazioni: TLD skipped. URI: http://java.sun.com/jsf/core is already defined
 set 08, 2014 2:14:12 PM org.apache.catalina.core.StandardContext listenerStart
 Grave: Exception sending context initialized event to listener instance of class org.apache.myfaces.webapp.StartupServletContextListener
 java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.application.ApplicationFactory. Attempting to find backup.
 	at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:800)
 	at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:302)
 	at org.apache.myfaces.context.servlet.FacesContextImplBase.getApplication(FacesContextImplBase.java:131)
 	at org.apache.myfaces.context.servlet.FacesContextImplBase.getELContext(FacesContextImplBase.java:180)
 	at javax.faces.component.UIViewRoot.setLocale(UIViewRoot.java:1450)
 	at org.apache.myfaces.webapp.AbstractFacesInitializer._createFacesContext(AbstractFacesInitializer.java:391)
 	at org.apache.myfaces.webapp.AbstractFacesInitializer.initStartupFacesContext(AbstractFacesInitializer.java:363)
 	at org.apache.myfaces.webapp.StartupServletContextListener.contextInitialized(StartupServletContextListener.java:105)
 	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4973)
 	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467)
 	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
 	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
 	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
 	at java.util.concurrent.FutureTask.run(Unknown Source)
 	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
 	at java.lang.Thread.run(Unknown Source)
 
 set 08, 2014 2:14:12 PM com.sun.faces.config.ConfigureListener contextInitialized
 Informazioni: Initializing Mojarra 2.1.6 (FCS 20120111) for context '/HelloJSF'
 set 08, 2014 2:14:13 PM com.sun.faces.spi.InjectionProviderFactory createInstance
 Informazioni: JSF1048: PostConstruct/PreDestroy annotations present.  ManagedBeans methods marked with these annotations will have said annotations processed.
 set 08, 2014 2:14:13 PM com.sun.faces.config.ConfigureListener$WebConfigResourceMonitor$Monitor <init>
 Informazioni: Monitoring jndi:/localhost/HelloJSF/WEB-INF/faces-config.xml for modifications
 set 08, 2014 2:14:13 PM org.apache.catalina.core.StandardContext startInternal
 Grave: Error listenerStart
 set 08, 2014 2:14:13 PM org.apache.catalina.core.StandardContext startInternal
 Grave: Context [/HelloJSF] startup failed due to previous errors
 set 08, 2014 2:14:13 PM org.apache.catalina.core.StandardContext listenerStop
 Grave: Exception sending context destroyed event to listener instance of class org.apache.myfaces.webapp.StartupServletContextListener
 java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.application.ApplicationFactory. Attempting to find backup.
 	at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:800)
 	at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:302)
 	at org.apache.myfaces.context.servlet.FacesContextImplBase.getApplication(FacesContextImplBase.java:131)
 	at org.apache.myfaces.context.servlet.FacesContextImplBase.getELContext(FacesContextImplBase.java:180)
 	at javax.faces.component.UIViewRoot.setLocale(UIViewRoot.java:1450)
 	at org.apache.myfaces.webapp.AbstractFacesInitializer._createFacesContext(AbstractFacesInitializer.java:391)
 	at org.apache.myfaces.webapp.AbstractFacesInitializer.initShutdownFacesContext(AbstractFacesInitializer.java:373)
 	at org.apache.myfaces.webapp.StartupServletContextListener.contextDestroyed(StartupServletContextListener.java:147)
 	at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:5014)
 	at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5659)
 	at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
 	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:160)
 	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
 	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
 	at java.util.concurrent.FutureTask.run(Unknown Source)
 	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
 	at java.lang.Thread.run(Unknown Source)
 
 set 08, 2014 2:14:13 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
 Grave: The web application [/HelloJSF] created a ThreadLocal with key of type [javax.faces.context.FacesContext$1] (value [javax.faces.context.FacesContext$1@2ce93ee6]) and a value of type [org.apache.myfaces.context.servlet.StartupFacesContextImpl] (value [org.apache.myfaces.context.servlet.StartupFacesContextImpl@5208513]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
 [WARN] Web application uses org.apache.axis2.transport.http.AxisAdminServlet; please update web.xml to use org.apache.axis2.webapp.AxisAdminServlet instead
 [INFO] Clustering has been disabled
 [INFO] Deploying module: addressing-1.6.2 - file:/C:/Users/Luca/workspace_EE/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Axis2WSTest/WEB-INF/modules/addressing-1.6.2.mar
 [INFO] Deploying module: jaxws-1.6.2 - file:/C:/Users/Luca/workspace_EE/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Axis2WSTest/WEB-INF/modules/axis2-jaxws-mar-1.6.2.mar
 [INFO] Deploying module: metadataExchange-1.6.2 - file:/C:/Users/Luca/workspace_EE/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Axis2WSTest/WEB-INF/modules/mex-1.6.2.mar
 [INFO] Deploying module: mtompolicy-1.6.2 - file:/C:/Users/Luca/workspace_EE/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Axis2WSTest/WEB-INF/modules/mtompolicy-1.6.2.mar
 [INFO] Deploying module: ping-1.6.2 - file:/C:/Users/Luca/workspace_EE/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Axis2WSTest/WEB-INF/modules/ping-1.6.2.mar
 [INFO] Deploying module: script-1.6.2 - file:/C:/Users/Luca/workspace_EE/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Axis2WSTest/WEB-INF/modules/scripting-1.6.2.mar
 [INFO] Deploying module: soapmonitor-1.6.2 - file:/C:/Users/Luca/workspace_EE/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Axis2WSTest/WEB-INF/modules/soapmonitor-1.6.2.mar
 [INFO] Deploying Web service: Converter - file:/C:/Users/Luca/workspace_EE/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Axis2WSTest/WEB-INF/services/Converter/
 [INFO] Deploying Web service: version-1.6.2.aar - file:/C:/Users/Luca/workspace_EE/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Axis2WSTest/WEB-INF/services/version-1.6.2.aar
 set 08, 2014 2:14:16 PM org.apache.coyote.AbstractProtocol start
 Informazioni: Starting ProtocolHandler ["http-bio-8080"]
 set 08, 2014 2:14:16 PM org.apache.coyote.AbstractProtocol start
 Informazioni: Starting ProtocolHandler ["ajp-bio-8009"]
 set 08, 2014 2:14:16 PM org.apache.catalina.startup.Catalina start
 Informazioni: Server startup in 11911 ms
 set 08, 2014 2:14:17 PM org.icepush.servlet.MainServlet <init>
 Informazioni: 
 ICEsoft Technologies Inc.
 ICEpush 3.3.0
 Build number: 11
 Revision: 34423
 
 set 08, 2014 2:14:20 PM org.icepush.servlet.EnvironmentAdaptingServlet <init>
 Informazioni: Adapting to Servlet 3.0 AsyncContext environment
 set 08, 2014 2:14:20 PM org.icepush.servlet.AsyncAdaptingServlet <init>
 Informazioni: Using Servlet 3.0 AsyncContext
 set 08, 2014 2:14:20 PM org.icepush.servlet.EnvironmentAdaptingServlet service
 Informazioni: Falling back to Thread Blocking environment
 WS invocation failed.
 java.lang.NullPointerException


******************************************************************************************************************************

In the class User.java I insert the initializzation of PortableRenderer and the invocation of Web Service.


Code:
private PortableRenderer pRenderer;
 private static final String PUSH_GROUP = "managerGroup";
 	
 public User(){
 	
 	PushRenderer.addCurrentSession(PUSH_GROUP);
 		
 	fcontext = FacesContext.getCurrentInstance();	
 		
 	HttpSession session = (HttpSession)fcontext.getExternalContext().getSession(true);
 	sessionId = session.getId();
 	
 	scontext = session.getServletContext();
 	
 	pRenderer = PushRenderer.getPortableRenderer(scontext);
 		
 }






Code:
public String notifyWS(){
 		
 	try {
 									
 		Object[] msg = {code, username, manager[0], manager[1]};
 			
 		String nameWS   = "http://localhost:8080/Prova_JSF/services/WebService"; 
 		
 		URL endPointWS  = new URL(nameWS); 
 		 
 		//initializzation WS 
 		Service service = new Service(); 
 		Call call       = (Call)service.createCall(); 
 		call.removeAllParameters(); 
 		 
 		call.setTargetEndpointAddress(endPointWS); 
 		call.addParameter("msg", XMLType.XSD_STRING, ParameterMode.IN); 		
 		call.setOperationName("notifyLogin"); 
 		call.setReturnType(XMLType.XSD_STRING); 
 		 
 		//invocation WS 
 		    
 	    	Object rispostaWS = call.invoke(new Object[]{msg}); 
 	    	String response = (String) rispostaWS;
 		    
 	}
 	catch (MalformedURLException ex){
 		System.out.println("Uncorrectly URL.");
 	}
 	catch(ServiceException ex){
 		System.out.println("WS creation failed.");
 	}
 	catch(RemoteException ex){
 		System.out.println("WS invocation failed.");
 		System.out.println(ex.toString());
 	}
 	    
 	return "ClientHome?faces-redirect=true";
 }


******************************************************************************************************************************

The Web Service contains only notifyLogin method in which I try unsuccessfully to make the renderer.


Code:
public class WebService {
 		
 	private PortableRenderer portableRenderer;
 	
 	HttpSession session;
 		
 	public String notifyLogin(String[] msg){
 					
 		FacesContext fcontext = FacesContext.getCurrentInstance();
 		
 		portableRenderer = PushRenderer.getPortableRenderer((ServletContext) fcontext);
        
 		portableRenderer.render("managerGroup");
 		
 		return "yes"; 
 	}
 }


******************************************************************************************************************************

Thanks for the help!
deryk.sinotte


Joined: 26/Oct/2004 00:00:00
Messages: 1008
Offline


Thanks for all the detailed info.

First of all, there seems to be an error even starting up your application:


Grave: Exception sending context initialized event to listener instance of class org.apache.myfaces.webapp.StartupServletContextListener java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.application.ApplicationFactory. Attempting to find backup. at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:800)
...
 


It might be worthwhile tackling that issue as it indicates that JSF is not initializing properly for some reason.

As for the PortableRenderer, the creation in the User constructor should be fine providing that the User bean is constructed during a servlet or JSF request as it will need access to the ServletContext. The ServletContext is necessary as that's where the PushContext is stored.

However, the WebService class will generally not be on a thread that originates as a JSF or servlet request and so will likely fail. As you've noted, since there is no access to the ServletContext, it can't propertly create a PortableRenderer.

Rather than have the WebService create and hold a reference to the PortableRenderer, would it be possible to change the design so that the WebService can call back into an application that does have a valid reference to the PortableRenderer? This could be your existing application or could be a separate application who's main responsibility is to handle notifications from the WebService in order to trigger push calls.

In short, instead of:

Code:
app login -> notifies web service -> calls PortableRenderer


the chain would add a layer and look more like:

Code:
app login -> notififies web service -> notifies some JSF app -> calls PortableRenderer

Deryk Sinotte
Team Lead
ICEsoft Technologies, Inc.
JackJack

Joined: 05/Sep/2014 07:44:24
Messages: 3
Offline


Hi, I apologize for the late reply but I had to modify some parts of the project.

Although I would have preferred to make a push directly from the web service, I followed your suggestion and it works!

But I have another problem ... When the manager is notified by the client with the pushRenderer a custom component should appear.

Unfortunately I can not catch the event of push notification and so I can not even call the javascript function to animate the custom component.

Thanks again for the help.
deryk.sinotte


Joined: 26/Oct/2004 00:00:00
Messages: 1008
Offline


Glad you got it working. Yes, the PushContext is stored in the ServletContext so, unless your Web Service can get or provide access to it, there's no real way to trigger the push that way.

Just to clarify, you are trying to determine when a push triggers an update in a client so that you can do some other work? In this case animate something in the UI?

Deryk Sinotte
Team Lead
ICEsoft Technologies, Inc.
deryk.sinotte


Joined: 26/Oct/2004 00:00:00
Messages: 1008
Offline


To my knowledge, there's no official way to capture a "push" directly in the client. There are documented callbacks you can register for that might be useful:

http://www.icesoft.org/wiki/display/ICE/JavaScript+Client+API

For example you might be able to make use of ice.onAfterUpdate(callback) or ice.onElementUpdate(elementID, callback) to determine whether the data that is being updated is relevant and trigger your animation. However, you might not be able to distinguish between an update originating from a Push vs an update originated from a standard user request. Or perhaps it makes no difference to your application.

A different approach would be to handle it on the server. A Push triggers a normal JSF lifecycle to occur so you could potentially change some state that could be detected on the client and then call your animation code.

More of longshot but perhaps you could even make use of the JavaScriptRunner utility:

http://res.icesoft.org/docs/v3_latest/core/api/

It allows you to send JavaScript as part of the update and get evaluated on the client.

Deryk Sinotte
Team Lead
ICEsoft Technologies, Inc.
 
Forum Index -> ICEpush General
Go to:   
Powered by JForum 2.1.7ice © JForum Team