Announcement

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

    DMI and DataSource

    Hi,

    i finally decided to put this problem onto this forum, i know it could be silly, but i m just too new to SmartGwt, really haven't got the idea yet.

    As how it's named, DMI is Direct Method Invocation, after some readings, DMI seems to me is not only for data fetching, removing, saving and updating, it can also call server methods from the client to perform some business logic, for example, clear the session to logout an authenticated user, or even something more complex. This understanding is pretty much based on my old experience in GwtExt, in which a RPC call can perform various tasks on the server side. Please tell me if i m right, or wrong?

    As described above, i m trying to do some simple examples, like a login, fill in username and password, click on a button, the server side DMI class will decide whether the given information is correct, hence react accordingly. From the SmartGwt/SmartGwtEE Showcase, almost all DMI calls are performed by a ListGrid, or some other components such as a DynamicForm.save, i m wondering how i can invoke a server method using a button, here's some sample code, but it doesn't work for me:

    userDmi.ds.xml
    Code:
        ......
        <serverObjecct lookupStyle="new" className="au.com.sample.trans.server.TransUserDMI" />
       
        <operationBindings>
            <binding operationType="fetch" operationId="tryLogin">
                <serverObject className="au.com.sample.trans.server.TransUserDMI" serverMethod="tryLogin"/>
            </binding>
        </operationBindings>
    client Java
    Code:
    		IButton buttonLogin = new IButton("Login");
    		buttonLogin.addClickHandler(new ClickHandler() {
    			
    			public void onClick(ClickEvent event) {
    				DSRequest request = new DSRequest();
    				request.setDataSource("userDmi");
    				request.setOperationId("tryLogin");
    //				RPCManager.sendRequest(request); **this method doesn't work, it requires changing actionUrl
    //				DMI.call(.....) ** found this from the smartgwtee javadoc, but can't find DMI class
    			}
    		});
    The 'DMI.call(....)' seems like what i wanted, but unfortunately i found the DMI class is not available, i guess it's in the SmartClient library, but isn't smartclient included by SmartGwt? I m getting even more confused, if i m going to use SmartGwt Pro, do i still need to download SmartClient and included it in my project class path? do i need to purchase a license for SmartClient library too?

    I think my problem is that i don't get the idea of how SmartGwt works, even i'm pretty familiar with GwtExt, but i really still have lots of questions.

    Please help me, i m planning for a new project using SmartGwt, coz i love the concept of getting rid of the redundant client side JavaBean in RPC in GwtExt, but i need to know that SmartGwt is a better choice before i m really putting this technology into our Enterprise project.

    Thanks! Your help is sincerely appreciated!
    Last edited by ledais0802; 5 Oct 2010, 19:15.

    #2
    Each package (SmartGWT and SmartClient) is self-contained, never mix files from two packages.

    First, start with the QuickStart Guide, especially the information in the SmartGWT Server Framework about DMI. You don't need to use DMI.call() - a typical way to represent a login operation is as a "fetch" operation on a "user" DataSource, where a successful login return the user's info as the result of the fetch.

    To trigger such a fetch, after creating a "user" DataSource with a DMI declaration (see QuickStart Guide), call DataSource.fetchData(), passing the credentials as criteria.

    Comment


      #3
      Thanks so much Iso, i think i sort of get it done, but i did this via creating a DSRequest, assign the datasource to it, and define the operationId of which to be executed. not sure if this is the right way of doing it.

      the following code is inside the button click action handler:
      Code:
      		DSRequest request = new DSRequest();
      		request.setDataSource("userDmi");
      		request.setOperationId("tryLogin");
      		Criteria cri = new Criteria();
      		String username = textItemUsername.getValue().toString();
      		String password = passwordItemPassword.getValue().toString();
      		cri.addCriteria("username", username);
      		cri.addCriteria("password", password);
      		datasource.fetchData(cri, new DSCallback() {
      			
      			@Override
      			public void execute(DSResponse response, Object rawData, DSRequest request) {
      				Record[] records = response.getData();
      				String s = "";
      				for(int i = 0; i < records.length; i ++) {
      					Record record = records[i];
      					String value = record.getAttribute("firstname");
      					s += value + ", ";
      				}
      				
      				SC.say(s);
      			}
      		}, request);
      Is there a better way of doing this?

      I also found something quite interesting, in the DMI definition XML file, if the binding tag is defined like this:
      Code:
              <binding operationType="fetch" operationId="tryLogin" serverMethod="tryLogin">
                  <serverObject className="au.com.sample.server.TransUserDMI"/>
              </binding>
      the request will call tryLogin method of the server class, but if i put the 'serverMethod' attribute into the 'serverObject' tag, like this:

      Code:
              <binding operationType="fetch" operationId="tryLogin" >
                  <serverObject className="au.com.sample.server.TransUserDMI" serverMethod="tryLogin"/>
              </binding>
      on the server log it says the operation to be invoked is 'tryLogin', but actually it invokes the default 'fetch' method. why is this happening?

      Comment


        #4
        Because the right place to put serverMethod is on the <operationBinding>. However you'll find that in recent nightly builds, it's accepted in either location.

        Comment


          #5
          Iso, thanks for that. as in my last post, is that the right way of doing such things? create a new DSRequest on the client side, pass it into the
          DataSource.fetchData(Criteria, DSCallBack, DSRequest)

          Comment


            #6
            Yes, that approach is fine and is the right way to specify the operationId. However note that you do not need to specify the DataSource on the dsRequest since you are already calling fetchData() on a specific DataSource.

            Comment


              #7
              Thanks Iso. I tried not to specify the DataSource on the dsRequest when 'fetchData()', unfortunately when the button is clicked it calls the default 'fetch'. did i miss anything? how do the DataSource and the newly created DSRequest link to each other though?

              Comment


                #8
                You need to create a DSRequest to specify the operationId in order to call your login operation. You do not need to call setDataSource() on it because you are already passing the dsRequest to the fetchData() method on the target DataSource.

                Comment


                  #9
                  get it! i found that myself too. now i think i m really getting onto it and having fun with this amazing thing. lots of thanks to you!

                  Comment

                  Working...
                  X