Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    OperationBinding defaultParams

    SmartClient Version: v9.1p_2015-01-30/PowerEdition Deployment (built 2015-01-30)

    I am trying to create a simple DMI Factory class that uses CDI to lookup an object. So I am trying to pass the objects class name via defaultParams in the ds.xml operation binding. However I cannot seem to figure out how to successfully set the value in xml. Perhaps you can shed some light on the subject for me?

    DMI Factory Class
    Code:
    public class CDIFactory {
    
        private final Logger LOGGER = Logger.getLogger(CDIFactory.class.getName());
    
        public Object create(HttpServletRequest request) throws Exception {
            String cdiBean = request.getParameter("cdiBean");
            LOGGER.warning("CDIFactory.create invoked with cdiBean = " + cdiBean);
            if(cdiBean == null) {
                throw new IllegalArgumentException("cdiBean parameter is required");
            }
            return CDI.current().select(Class.forName(cdiBean)).get();
        }
    
    }
    ds.xml
    Code:
    <serverObject className="com.sncorp.gs2.gsui.server.dmi.CDIFactory" lookupStyle="factory"/>
        <operationBindings>
            <operationBinding operationType="custom" operationId="test1" serverMethod="test1">
                <defaultParams>
                    <valueMap cdiBean="com.sncorp.dmi.Test"></valueMap>
                </defaultParams>
            </operationBinding>
            <operationBinding operationType="custom" operationId="test2" serverMethod="test2">
                <defaultParams>
                    <valueMap cdiBean="com.sncorp.dmi.Test"></valueMap>
                </defaultParams>
            </operationBinding>
            <operationBinding operationType="custom" operationId="test3" serverMethod="test3">
                <defaultParams>
                    <valueMap cdiBean="com.sncorp.dmi.Test"></valueMap>
                </defaultParams>
            </operationBinding>
        </operationBindings>
    However, the parameter cdiBean does not exist in the HttpServletRequest.

    #2
    I have also tried using

    <valueMap>
    <value ID="cdiBean">className</value>
    </valueMap>

    to no avail

    Comment


      #3
      Hmm, we didn't cover this in the docs, but defaultParams does not apply to dataProtocol:"iscServer" (what you're implicitly using when using a .ds.xml file); it was designed for integration with third-party servers.

      You probably don't want to use HTTP params for this purpose, because of DSRequest equivalence among other concerns.

      Other approaches would be:

      1. dsRequest.operationId

      2. dsRequest modifiers (<criteria> or <values> tags under the operationBinding)

      Comment


        #4
        So I went digging into OperationBinding.ds.xml and found:

        <defaultParams type="Object"/>

        rather than type="ValueMap" as I would have expected, should I infer from this that this value must be set programmatically? That is significantly less than optimal for what I am trying to achieve here.

        Comment


          #5
          For reference, correct syntax would have been:

          Code:
                  <operationBinding operationType="custom" operationId="test3" serverMethod="test3">
                      <defaultParams>
                          <paramName>paramValue</paramName>
                      </defaultParams>
                  </operationBinding>

          Comment


            #6
            I do not understand how I can set something on the ds request, as I cannot have a create(DSRequest dsRequest) factory method, as it returns an error stating it could not find an appropriate value to place in slot 1.

            ***edit***
            I had initially thought I could just add an extra attribute to the operationBinding itself and retrieve it from the dsRequest in the factory method via dsRequest.getOperationConfig().get("cdiBean"), when I realized the smartgwt server failed to inject the DSRequest
            Last edited by jpappalardo; 24 Feb 2015, 14:45.

            Comment


              #7
              We're not suggesting that - please take a look at the docs for each of the approach mentioned, they have nothing to do with creating a DSRequest manually.

              Comment


                #8
                I do not understand how what you are saying is going to help me achieve my goal, I am trying to create a single factory method that can return an object via cdi to perform a dmi call as specified in xml.

                Ultimately the goal is to get away from having proxy classes in our code, that simply delegates to another class in a bundled ejb-jar. By pointing the dmi methods whether ds or rpc directly to the managed bean in another deployment.

                Comment


                  #9
                  In both approaches, you will have something on the DSRequest that your CDI code can use to do whatever dispatching you need. For instance, in the case of a <value> DSRequestModifier, you'd be able to affect the result of DSRequest.getValues().

                  However perhaps a more basic question: why are you trying to get more information into the <operationBinding> at all, when your operationIds (at least as shown in the sample) are already unique? Why not just use the operationId to look up the corresponding cdiBean - do you have some specific reason to put it in the .ds.xml file?

                  Also: you realize that "factory" mode is intended to provide an object that the DMI will be invoked on? The object returned by "factory" mode is not intended to directly process the request, so it's not passed the request.

                  Comment


                    #10
                    I feel as though we are not on the same page as to what I am trying to accomplish here. I would like to create a dmi factory that uses cdi to return the object to invoke the method on. I am trying to leverage the reflection mechanism you have already written to invoke the method with the correct parameters already. However, somehow I need the factory method to be able to be passed the class name it should select from the cdi context.

                    The goal here is a generic factory that can return any cdi managed bean to perform dmi whether it be a datasource or rpc dmi method. The present solution we have in place requires a factory class for every managed bean.

                    Comment


                      #11
                      We think we've addressed this, and it seems like you are having trouble because you have a basic assumption that you'll be using lookupStyle="factory" (not necessarily indicated) and that the classNames must appear in the .ds.xml file (not necessarily the best approach).

                      Let's try rephrasing again.

                      You want to declare a series of operationBindings such that in the processing code (not necessarily a factory) you can determine what CDI className to use (not necessarily passed in).

                      A simple way to do this, since all of your operationBindings seem to have unique operationIds, is to use a normal, non-factory DMI at the DataSource level and look up the CDI className using the operationId. The lookup mechanism could use the .ds.xml to store the operationId<->className mappings or could store them somewhere else (server.properties for instance), it's up to you.

                      Comment


                        #12
                        So in essence I have no choice but to rewrite your reflection mechanism in order to use cdi.

                        Comment


                          #13
                          ??

                          We find that a bizarre way of putting it. You're already planning to use reflection to look up a CDI class, the framework isn't forcing you to use reflection in any additional or spurious way.

                          A more accurate way of putting it is to simply say that there are many ways of doing what you want to do, and the "factory" mechanism wasn't intended for your use case.

                          By the way, there is CDI support in 6.0, and it's done via a new lookupStyle="cdi". But we doubt you're ready to move to that version.

                          Comment


                            #14
                            For the record...

                            The ability to pass in a DSRequest into a DMI factory class appears to have been fixed. Using that fix I was able to get the following to work.

                            ds.xml
                            Code:
                            <operationBindings>
                                    <operationBinding operationType="custom" operationId="test" serverMethod="test">
                                        <serverObject className="com.acme.dmi.DataSourceDMIFactory" lookupStyle="factory" bean="com.acme.Test"/>
                                    </operationBinding>
                                </operationBindings>
                            DataSourceDMIFactory
                            Code:
                            public class DataSourceDMIFactory {
                            
                                private final Logger logger = Logger.getLogger(DataSourceDMIFactory.class.getName());
                            
                                public Object create(DSRequest request) throws Exception {
                                    Map serverObjectConfig = (Map) request.getDataSource().getOperationBinding(request.getOperationType(), request.getOperationId()).get("serverObject");
                                    if(serverObjectConfig == null)
                                        serverObjectConfig = request.getDataSource().getServerObjectConfig();
                                    String bean = (String) serverObjectConfig.get("bean");
                                    return CDI.current().select(Class.forName(bean)).get();
                                }
                            }
                            app.xml
                            Code:
                            <Application>
                                <rpcBindings>
                                    <ServerObject ID="Test" className="com.acme.dmi.RPCDMIFactory" lookupStyle="factory"
                                                  bean="com.acme.Test">
                                        <visibleMethods>
                                            <method name="dtedLookup"/>
                                        </visibleMethods>
                                    </ServerObject>
                                </rpcBindings>
                            </Application>
                            RPCDMIFacotry
                            Code:
                            public class RPCDMIFactory {
                            
                                public Object create(RPCRequest request) throws Exception {
                                    Map appConfig = RPCDMI.loadAppConfig(request.getAppID());
                                    List<Map> rpcBindings = (List) appConfig.get("rpcBindings");
                                    Map serverObjectConfig = null;
                                    for(Map serverObject : rpcBindings) {
                                        if(serverObject.get("ID").equals(request.getServerObjectID())) {
                                            serverObjectConfig = serverObject;
                                            break;
                                        }
                                    }
                                    if(serverObjectConfig == null)
                                        throw new RuntimeException("some message");
                                    String bean = (String) serverObjectConfig.get("bean");
                                    return CDI.current().select(Class.forName(bean)).get();
                                }
                            }

                            Comment

                            Working...
                            X