Can I pass an Object to a viewscoped bean?

Splash Forums Rewrite Users Can I pass an Object to a viewscoped bean?

This topic contains 8 replies, has 2 voices, and was last updated by  cilf 1 year, 8 months ago.

Viewing 9 posts - 1 through 9 (of 9 total)
  • Author
    Posts
  • #26457

    cilf
    Participant

    I know I can get viewscoped bean to load by

    
    PhaseOperation.enqueue(
        Invoke.binding(El.retrievalMethod("controller.load"))
    ).after(PhaseId.RESTORE_VIEW)
    

    but can I pass it an Object? I was trying to mess around with El.submissionMethod but no luck :-/

    Thanks

    #26460

    The El.submissionMethod() assumes that you are passing an expression which is used to evaluate the target for the a bound parameter to be submitted. (The value comes from the parameter.) I’m not exactly sure what you’re trying to do, but you should probably use Invoke.binding(submission, retrieval).

    Invoke.binding(El.submissionMethod("#{myEl.methodName}"), new Retrieval() {
       public Object retrieve(Rewrite event, EvaluationContext context)
       {
          Object myObject = ...;
          return myObject;
       }
    })
    #26461

    If this is a use case that sees common use, I’d recommend creating a utility to do this. It’s possible we could bring it into the framework on the Invoke class itself if the use-case is good and not covered by something else (or a simpler way of achieving the result.)

    #26471

    cilf
    Participant

    Well I have a following rule

    .addRule()
    .when(Direction.isInbound().and(Path.matches("/{artistUrl}")))
    .perform(
            new HttpOperation() {
                @Override
                public void performHttp(HttpServletRewrite event, EvaluationContext context) {
                    final String artistUrl = (String) Evaluation.property("artistUrl").retrieve(event, context);
    
                    final Artist artist = artistService.findByUrl(artistUrl);
    
                    if (artist == null) {
                        Perform.all(Response.setStatus(404), Forward.to("/404.xhtml?message=artist-not-found")).perform(event, context);
                        return;
                    }
    
                    Perform.all(
                            PhaseOperation.enqueue(
                                    Invoke.binding(El.retrievalMethod("artistPage.load"))
                            ).after(PhaseId.RESTORE_VIEW),
                            Forward.to("/artist-page.xhtml")
                    ).perform(event, context);
                }
            })
    .where("artistUrl").matches("[a-z0-9-]+").bindsTo(PhaseBinding.to(El.property("controller.artistUrl")).after(PhaseId.RESTORE_VIEW))
    

    and Controller.java

    @Named
    @ViewScoped
    public class Controller implements Serializable {
    
        @Inject
        private ArtistService artistService;
        
        private Artist artist;
    
        private String artistUrl;
    
        public void load() {
            artist = artistService.findByUrl(artistUrl);
        }
    
        // setters & getters
    }
    

    which is working fine. The thing I don’t like about it is that it calls the artistService.findByUrl twice – once in ConfigurationBuilder and once in Controller

    I was hoping to reuse the artist object that I have from Configuration so that I don’t have to load it again in Controller. You suggested

    .addRule()
    .when(Direction.isInbound().and(Path.matches("/{artistUrl}")))
    .perform(
            new HttpOperation() {
                @Override
                public void performHttp(HttpServletRewrite event, EvaluationContext context) {
                    final String artistUrl = (String) Evaluation.property("artistUrl").retrieve(event, context);
    
                    final Artist artist = artistService.findByUrl(artistUrl);
    
                    if (artist == null) {
                        Perform.all(Response.setStatus(404), Forward.to("/404.xhtml?message=artist-not-found")).perform(event, context);
                        return;
                    }
    
                    Perform.all(PhaseOperation.enqueue(
                            Invoke.binding(El.submissionMethod("#{controller.setArtist}"), new Retrieval() {
                                public Artist retrieve(Rewrite event, EvaluationContext context) {
                                    return artist;
                                }
                            })
                    ).after(PhaseId.RESTORE_VIEW), Forward.to("/artist-page.xhtml")).perform(event, context);
                }
            })
    .where("artistUrl").matches("[a-z0-9-]+")
    

    but it gives me

    16:29:58,099 ERROR [io.undertow.request] (default task-31) UT005023: Exception handling request to /artist-page.xhtml: javax.servlet.ServletException: Failed to handle PhaseOperation [org.ocpsoft.rewrite.faces.config.PhaseOperation$DeferredOperation@1df02d48]
    	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:659) [jboss-jsf-api_2.2_spec-2.2.6.jar:2.2.6]
    	at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:130) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:226) [rewrite-servlet-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:229) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchToPath(ServletInitialHandler.java:172) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.spec.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:159) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at org.ocpsoft.rewrite.servlet.impl.HttpRewriteResultHandler.handleResult(HttpRewriteResultHandler.java:41) [rewrite-servlet-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.servlet.RewriteFilter.rewrite(RewriteFilter.java:297) [rewrite-servlet-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:198) [rewrite-servlet-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:113) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    	at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:177) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:727) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_67]
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_67]
    	at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_67]
    Caused by: org.ocpsoft.rewrite.exception.RewriteException: Failed to handle PhaseOperation [org.ocpsoft.rewrite.faces.config.PhaseOperation$DeferredOperation@1df02d48]
    	at org.ocpsoft.rewrite.faces.RewritePhaseListener$1.performInSubflow(RewritePhaseListener.java:149) [rewrite-integration-faces-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.servlet.event.SubflowTask.perform(SubflowTask.java:61) [rewrite-servlet-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.faces.RewritePhaseListener.handlePhaseOperation(RewritePhaseListener.java:127) [rewrite-integration-faces-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.faces.RewritePhaseListener.handleAfterPhaseOperations(RewritePhaseListener.java:110) [rewrite-integration-faces-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.faces.RewritePhaseListener.afterPhase(RewritePhaseListener.java:64) [rewrite-integration-faces-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at com.sun.faces.lifecycle.Phase.handleAfterPhase(Phase.java:189) [jsf-impl-2.2.6-jbossorg-4.jar:]
    	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:107) [jsf-impl-2.2.6-jbossorg-4.jar:]
    	at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:121) [jsf-impl-2.2.6-jbossorg-4.jar:]
    	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198) [jsf-impl-2.2.6-jbossorg-4.jar:]
    	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646) [jboss-jsf-api_2.2_spec-2.2.6.jar:2.2.6]
    	... 45 more
    Caused by: java.lang.NullPointerException
    	at com.sun.el.util.ReflectionUtil.paramString(ReflectionUtil.java:210) [javax.el-3.0.0.jar:]
    	at com.sun.el.util.ReflectionUtil.getMethod(ReflectionUtil.java:160) [javax.el-3.0.0.jar:]
    	at com.sun.el.parser.AstValue.invoke(AstValue.java:272) [javax.el-3.0.0.jar:]
    	at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304) [javax.el-3.0.0.jar:]
    	at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40) [weld-core-impl-2.1.2.Final.jar:2014-01-09 09:23]
    	at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50) [weld-core-impl-2.1.2.Final.jar:2014-01-09 09:23]
    	at org.ocpsoft.rewrite.cdi.expressions.Expressions.evaluateMethodExpression(Expressions.java:215) [rewrite-integration-cdi-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.cdi.expressions.Expressions.evaluateMethodExpression(Expressions.java:339) [rewrite-integration-cdi-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.cdi.CdiExpressionLanguageProvider.evaluateMethodExpression(CdiExpressionLanguageProvider.java:111) [rewrite-integration-cdi-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.el.El$ElMethod$2.call(El.java:238) [rewrite-servlet-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.el.El.executeProviderCallable(El.java:171) [rewrite-servlet-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.el.El.access$100(El.java:40) [rewrite-servlet-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.el.El$ElMethod.submit(El.java:233) [rewrite-servlet-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.config.Invoke.perform(Invoke.java:58) [rewrite-servlet-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.faces.config.PhaseOperation$1.performOperation(PhaseOperation.java:80) [rewrite-integration-faces-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	at org.ocpsoft.rewrite.faces.RewritePhaseListener$1.performInSubflow(RewritePhaseListener.java:134) [rewrite-integration-faces-3.0.0.Alpha3.jar:3.0.0.Alpha3]
    	... 54 more
    

    Am I doing something wrong?

    #26473

    I think what you’re doing should be done using a Validator and Converter instead… I think you’re overcomplicating things by doing this all in the .perform() clause:

    .addRule()
    .when(Direction.isInbound().and(Path.matches("/{artistUrl}")))
    .perform(Forward.to("/artist-page.xhtml"))
    .where("artistUrl")
       .validatedBy(new Validator() {...do db query to see if object exists...})
       .convertedBy(new Converter() {...do db query to convert string artistUrl to desired object...} )
    .bindsTo(El.submissionMethod("#{controller.setArtist}"))

    The converter/validator should look up the value in the database and check to see if it’s there. If you need to cache the value so that it’s not looked up twice, then consider using .configuredBy() instead, so that one object handles the validation and conversion of the entire parameter:

    
    public class MyValidatingConverter implements Validator, Converter {
       ...
    }
    
    ...
    
    MyValidatingConverter configurator = new MyValidatingConverter();
    
    ...
    
    .addRule()
    .when(Direction.isInbound().and(Path.matches("/{artistUrl}")))
    .perform(Forward.to("/artist-page.xhtml"))
    .where("artistUrl")
       .configuredBy(configurator)
       .convertedBy(configurator)
    .bindsTo(El.submissionMethod("#{controller.setArtist}"))
    #26475

    cilf
    Participant

    But then I’m gonna need one more rule for handling 404 (artist not found). I kind of liked the single perform operation per inbounding url and the simple if-else case for existing artist.

    I have a feeling that the music app requirements will get more complicated – like checking if an album from /{artistUrl}/{albumUrl} really belongs to the artist and I don’t want to end up in a rule mess. Things can get pretty confusing when the evaluation depends on the rules order and stuff like .withPriority ๐Ÿ™‚

    I’ll see what I can do with .bindsTo(El.submissionMethod("#{controller.setArtist}")).. Thanks for the info though. I didn’t find it anywhere in docs.

    #26478

    Yeah, just FYI, typically what you are doing would be done (in JSF) by simply using a join, then handling this using the tag of the XHTML page itself. Then you can forward/send to 404/or handle navigation a little more smoothly, since you’re already in an initialized JSF environment:

    	<f:metadata>
    		<f:viewParam name="id" value='#{artistBean.artistUrl}' />
    		<f:event type="preRenderView" listener='#{artistBean.retrieve}' />
    	</f:metadata>

    (If the retrieve method doesn’t find anything, then you send to artist 404 page.)

    Of course you can do this in rewrite, using things like Subset to split .perform() clause functionality into nested rules:

    https://github.com/ocpsoft/redoculous/blob/master/app/src/main/java/org/ocpsoft/redoculous/config/LocalFilesystemConfigurationProvider.java#L63

    #26479
    #26541

    cilf
    Participant

    Yeah, just FYI, typically what you are doing would be done (in JSF) by simply using a join, then handling this using the tag of the XHTML page itself. Then you can forward/send to 404/or handle navigation a little more smoothly, since youโ€™re already in an initialized JSF environment:

    Yup I ended up doing exactly that. Thanks for the advice.

    As for passing the object to the viewscoped bean I managed to get it running just by simply injecting the bean into a @RewriteConfiguration class via CDI and using it as I needed. Thanks for the help ๐Ÿ™‚

Viewing 9 posts - 1 through 9 (of 9 total)

You must be logged in to reply to this topic.

Comments are closed.