Announcement

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

  • Blama
    replied
    Originally posted by ankulchoudhary View Post
    Hi isomorphic,

    What is the best approach to use global variables in smartgwt? I have some variables which should be loaded once globally and can be used later on as required. For more specifically, I have some configurable constants which are going to be retrieved from the server. I want to load these variables on page load in some global variables at smartgwt end use them later on. Can you suggest some approach with some example?
    Regards
    Ankul
    I'm using sth like this (don't know if it is the best approach because it delays the UI drawing by 1 server roundtrip, but I need the info before drawing the UI):

    In onModuleLoad:
    Code:
    final SettingsCache sc = SettingsCache.getInstance();
    sc.refresh(new RPCQueueCallback() {
                        @Override
                        public void execute(RPCResponse... response) {
                            // Show tabs (depending on user grants)
                            mainLayout = new MainLayout();
                            mainLayout.draw();
    SettingsCache-singleton contains the logic to store the needed global vars.
    Code:
        public void refresh(final RPCQueueCallback rpcQueueCallback) {
            RPCManager.startQueue();
            settingsAndDefaultsDS.fetchData(null, new DSCallback() {
            ...
            ...
    
    ...many requests...
    ...many requests...
    
            RPCManager.sendQueue(rpcQueueCallback);
        }
    Now in the application I get the singleton wherever I need it and have many many getters there for my global settings that come from the DB.

    Best regards
    Blama

    Leave a comment:


  • ankulchoudhary
    replied
    Hi isomorphic,

    What is the best approach to use global variables in smartgwt? I have some variables which should be loaded once globally and can be used later on as required. For more specifically, I have some configurable constants which are going to be retrieved from the server. I want to load these variables on page load in some global variables at smartgwt end use them later on. Can you suggest some approach with some example?
    Regards
    Ankul

    Leave a comment:


  • Isomorphic
    replied
    Start by posting both the server-side log for the request as well as the response from the server as seen in the SmartGWT Developer Console RPC tab.

    Leave a comment:


  • ankulchoudhary
    replied
    Hi isomorphic,

    I am trying to get JSON object from server using RPC manager. I am sending a Map(java.util.Map) from server using REST. Getting data as well on client side. But the issue is that I am unable to convert that data in Map or any other object at client side. Here is my code snipet:
    Client side:
    RPCRequest request = new RPCRequest();
    request.setHttpMethod("GET");
    request.setContentType("application/json");
    request.setActionURL("/resource/cms/end-points");
    request.setUseSimpleHttp(true);
    RPCManager.sendRequest(request, new RPCCallback() {
    @Override
    public void execute(RPCResponse response, Object rawData, RPCRequest request) {
    try {
    // JavaScriptObject jso = response.getDataAsMap();
    Map<String,String> map = response.getDataAsMap();

    String msg = map.get("viewNewsUrl");
    GWT.log(msg);
    }
    catch(Exception ex) {
    GWT.log(ex.getLocalizedMessage());
    GWT.log(ex.getMessage());
    GWT.log(ex.toString());
    }
    }
    });

    Server side code is:
    @Controller
    @RequestMapping("/resource")
    public class ResourceResolverController {

    @RequestMapping(value="/cms/end-points", method = RequestMethod.GET, headers = "Accept="
    + MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public Map<String, String> getCMSContentUrls(HttpServletRequest request, HttpServletResponse response) {

    Map<String, String> cmsContentUrls = new LinkedHashMap<String, String>();
    cmsContentUrls.put("viewNewsUrl", "some url");
    cmsContentUrls.put("addNewsUrl", "some url");
    cmsContentUrls.put("viewEventsUrl", "some url");
    cmsContentUrls.put("addEventsUrl", "some url");

    return cmsContentUrls;

    }
    }

    Getting below exception:

    convertToMap - unable to convert the passed JavaScript object to a Map. JavaScript is: "{"viewNewsUrl":"some url","addNewsUrl":"some url","viewEventsUrl":"some url","addEventsUrl":"some url"}"
    SuperDevModeLogger.java:71 convertToMap - unable to convert the passed JavaScript object to a Map. JavaScript is: "{"viewNewsUrl":"some url","addNewsUrl":"some url","viewEventsUrl":"some url","addEventsUrl":"some url"}"
    SuperDevModeLogger.java:71 java.lang.IllegalArgumentException: convertToMap - unable to convert the passed JavaScript object to a Map. JavaScript is: "{"viewNewsUrl":"some url","addNewsUrl":"some url","viewEventsUrl":"some url","addEventsUrl":"some url"}"

    I have tried multiple ways to map data at client side like below:

    JavaScriptObject jso = (JavaScriptObject)rawData; Map<String,String> map = (Map<String,String>)JSOHelper.convertToMap(jso);

    Leave a comment:


  • Isomorphic
    replied
    Yes, we defined the .ds.XML format. However it is the Java platform that defines that a Java Bean's properties exist because of getter/setter pairs with a particular naming convention, and that given a getter/setter pair like getBlah() / setBlah(), the name of the property is considered to "blah" with a lowercase B.

    Leave a comment:


  • pmac
    replied
    Originally posted by Isomorphic
    ...definition of a Java Bean, not something we came up with.
    Did you define the DS.xml file format? I was left confused because when you were saying the fields didn't match the getter/setter, I was thinking that the *member* names had to match the getter/setter, not the XML field names. I figured the serialization code looked at the bean *only* and said "Oh, I have these members and corresponding getter/setters, so I'll serialize these key-value pairs into the response."

    This is also what I was expecting to happen when when I started this thread and tried to figure out how to throw a bean into the response and have the platform send it back to the server (as a map or whatever). This all makes it much clearer (at least for me).

    Thanks for the help.

    Leave a comment:


  • Isomorphic
    replied
    All correct. However just to clarify, what you've just explained is the Java platform's definition of a Java Bean, not something we came up with.

    Leave a comment:


  • pmac
    replied
    Ok, I figured it out. I'll give a little more context so others can follow.

    My example is for searching "project" records:

    ProjectRecord.java
    Code:
    public class ProjectRecord  {
    	protected Long projectID_;  // member name doesn't matter here!
    	protected String name_;
    
    	public ProjectRecord() {}
    
    	public void setProjectID(Long projectID) { projectID_ = projectID; }
    	public void setName(String name) { name_ = name; }
    
    	public Long getProjectID() { return projectID_; }
    	public String getName() { return name_; }
    }
    ProjectDMI.ds.xml:
    Code:
    <DataSource
    	ID="ProjectDMI"
    	serverType="sql"
    	clientOnly="false"
    >
    	<fields>
    		<field name="projectID" type="sequence" hidden="true" primaryKey="true" />
    		<field name="name" type="text" required="true" length="50" />
    	</fields>
    
    	<operationBindings>
    		<operationBinding operationType="fetch" serverMethod="fetch" operationId="search" >
    			<serverObject lookupStyle="new" className="com.foobar.testapp.server.dmi.SearchProjectsDMI" />
    		</operationBinding>
      	</operationBindings>
    </DataSource>
    SearchProjectsDMI.java:
    Code:
    public class SearchProjectsDMI {
    	public DSResponse fetch(DSRequest dsRequest) throws Exception
    	{
    		List projectRecords = new ArrayList();
    		for(int ii = 1; ii <= 5; ++ii) {
    			ProjectRecord rec = new ProjectRecord();
    			rec.setProjectID(ii);
    			rec.setName("Proj-"+ii);
    			projectRecords.add(rec);
    		}
    
    		DSResponse dsResponse = new DSResponse();
    		dsResponse.setDataSource(dsRequest.getDataSource());
    		dsResponse.setStartRow(0);
    		dsResponse.setEndRow(projectRecords.size());
    		dsResponse.setTotalRows(projectRecords.size());
    		dsResponse.setData(projectRecords);
    
    		return dsResponse;
    	}
    }
    So, what was I missing? Well, I had the "name" of each field in the ProjectDMI.ds.xml as uppercase (i.e. "ProjectID" and "Name"), whereas they *MUST* be lowercase (i.e. "projectID" and "name").

    To be clear:
    1. The field names in the XML doc must begin with lowercase.
    2. The corresponding getter and setter in the bean must be of the form "getProjectID()" and "setProjectID()".
    3. (Bonus): the protected/private data members in the bean don't matter...they can be uppercase, lowercase, abbreviations, or even represented as a map...for the bean, it's the getters/setters only (I haven't tested this point exhaustively, but it's my strong belief).

    One more interesting thing: when I set the dropExtraFields="false" in the DataSource, it will serialize the fields found in the bean, even when the Datasource field names start with uppercase letters. However, the serialized map representation has all names starting with lowercase (i.e. it appears as "projectID" and "name"). To me, this means that the serializer is just using all of the getters and creating corresponding entries in the map that start with the lowercase letter of the getter's field name.

    Hope this helps someone!

    Leave a comment:


  • pmac
    replied
    For the serialization of the records to occur upon returning a response, does the DataSource XML doc need to define the serverType as "generic", or can I define it as "sql"?

    Thanks.

    Leave a comment:


  • Isomorphic
    replied
    Java Bean properties discovered by reflection will be sent to the client. There is no need for the object to be Serializable, in fact, part of the point is elimination of DTOs.

    See also DataSource.dropExtraFields, on by default for DMI - most likely if you are seeing empty maps, your field names do not match the getter/setter names.

    Leave a comment:


  • pmac
    replied
    One thing that isn't clear to me is how the DMI samples work. I haven't actually gotten the sample code to run on my local computer. I have my own DMI app that I think I'm doing the same thing the DMI samples do. It returns a List of bean objects, and the DevConsole shows the correct number of items in the list, but each list item is an empty map.

    Specifically, does the bean actually get serialized and passed back across the wire? If so, what are the requirements to make that happen?

    I.e. the samples imply that following would be serialized and returned by via a DMI-fetch's response:

    Code:
    public class MyBean implements Serializable {
    	protected String name;
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public String getName() {
    		return name;
    	}
    }
    Thanks!

    Leave a comment:


  • Isomorphic
    replied
    Ah, got it. Now that makes sense :)

    Leave a comment:


  • pmac
    replied
    Sorry, didn't mean to confuse the issue.

    I was just saying that as a half-way step from where I started (notify -> fetch -> update), that I was able to get rid of the update to be (notify -> fetch -> updateCaches).

    I agree that it'll be better to pass the details of the record as part of the notify, but I hadn't gotten that far yet. I'm working on that part next.

    Leave a comment:


  • Isomorphic
    replied
    Not really following that.. seems as though you are overcomplicating things. The typical pattern is that when you receive data in your Messaging subscriber, you create a DSResponse (new DSResponse()) using the data you received via Messaging and pass that DSResponse to updateCaches().

    If, for whatever reason, you are not able to send the changed data via Messaging, but you able to get an ID for the updated record, then yes you can do a separate DataSource.fetchData() call to get the complete record. However, re-using the DSResponse you receive in the callback from fetchData() is an unnecessary hack. Just create a new one (new DSResponse()) and populate it.

    Leave a comment:


  • pmac
    replied
    Ok, I see. The following is to hopefully help anyone else reading along...

    As a intermediate step for now, the following seems to work: Once I receive the DSResponse/DSRequest in the "fetch" DSCallback, I can then set the DSRequest.setOperationType() from "fetch" to be "update" and just pass the response/request to dataSource.updateCaches(dsResponse, dsRequest). Doing this eliminates me doing an extra (and possibly error-causing) datasource.update() to accomplish the same goal (of having databound components observe the new record).

    I'll look into sending the updated record from the server-side next.

    Thanks very much!

    Leave a comment:

Working...
X