Announcement

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

  • Isomorphic
    replied
    To recap:

    1. We showed you an approach that allows any development mode to be used, and doesn't involve using APIs in an unsupported manner

    2. You prefer an approach that restricts testing to compiled mode, requires teams to closely coordinate to ensure obfuscated names match perfectly, and uses SmartGWT APIs in an unsupported manner

    It's nice that you have that preference, but, as far as this becoming a supported usage of SmartGWT, we would not accept a project to take approach #2, since it's obviously worse in every way - more effort for a much much less usable solution.

    Leave a comment:


  • ssequeira
    replied
    "Yes, if you look at compiled mode only, and you set things up so that both projects use the exact same obfuscated names, you can get through the limited demo you've shown, because one application will actually use the wrapper object from the other application, not realizing it is even a foreign application's object. "

    This works for me, limited as it may be.

    Leave a comment:


  • Isomorphic
    replied
    Yes, if you look at compiled mode only, and you set things up so that both projects use the exact same obfuscated names, you can get through the limited demo you've shown, because one application will actually use the wrapper object from the other application, not realizing it is even a foreign application's object.

    We were already aware of this.

    The reason we didn't bring it up is that it is yet another useless result: it's not reasonable to limit testing to only compiled mode, nor is it reasonable to impose all the rules that would guarantee perfectly matching obfuscated names - certainly not when other approaches, like the one we showed 5 years ago, have no such limitations!

    If you want to see the issues we are talking about, run in other modes, or just compile in such a way that obfuscated names won't match.

    I approached Isomorphic before starting the thread, asking which way would be the best to handle this case. You, Isomorphic, pointed me to write a thread in the forum.
    We did indeed invite you to post to the forums, anticipating a fruitful Q&A session. We certainly did not expect you would start a long thread repeatedly and erroneously trying to contradict our answers, which has been a monumental waste of time - remember, we showed you the right way to do this 5 years ago!

    When you are ready to proceed with the working approach, let us know, and we can estimate the remaining work.

    In the meantime, please understand that we can't waste any more time explaining exactly how you are going down a dead end. We've covered the same basic concept (obfuscated names won't match) in 3 or 4 different guises now, you have more than enough information to connect the remaining dots on your own, without further help from us.

    Leave a comment:


  • ssequeira
    replied
    "Canvas.getById() didn't exist 5 years ago either"

    It did.

    "It's the same approach. Libraries for doing interapp communication did not exist 5 years ago, so the "boilerplate" you're referring to is just a PoC-level implementation of the same approach used by interapp."

    It's not a library, it's a pattern.

    "Canvas.getById() was designed for retrieving widgets created by Component XML, it assumes there is no other GWT application around that also has a reference to the underlying SmartClient widget. So when you retrieve a widget this way, you either create a duplicate SmartGWT wrapper for the underlying SC widget, or one GWT app tries to re-use the wrapper from another."

    Which one is it? Duplicate wrapper or re-using the wrapper. Can they both happen? If yes, is it random? If not, what decides which behavior is applied?
    Am I wrong to assume you would know these details?


    From your answers I can't honestly figure out if the use case is valid or not, because throughout your threads you simple state things you believe are facts but are not. And for the concerns you have, you haven't been able to list a single measurable evidence that they are valid. You just consider them valid because you don't support the use case.

    -----------------

    Memory leak.

    Click image for larger version

Name:	profile_poc_interapp.png
Views:	317
Size:	145.0 KB
ID:	237539

    See attachment for better visualization.
    If you are interested in the raw data I can provide it. I have both timeline and heapprofile.
    ~2 minute usage / portlets were added and destroyed at a rate of 1/0.5sec.

    I haven't done many profiles, especially on JS side, but I'd think this is not a profile which screams memory leak. If it is, you also have a problem in the standard use case, since they look pretty much the same.

    ------------------

    "...crash either at the typecast, or on subsequent invocations, because the method names are obfuscated differently. Which behavior happens probably depends on which version of SmartGWT you're using, because we've made changes over the years in how wrappers are allocated and tracked."

    No crash happened so far. So we can dismiss this concern? If a crash or error were to happen, we would see it, no?

    ------------------

    "It also depends on the mode you're running in (compiled vs SDM vs classic DevMode)."

    I am interested in compiled mode only, no need to bring new variables to the mix...

    ------------------

    "If we wanted to actually support this use case, we'd need to make a variety of different changes and set up a few new APIs, create docs describing exactly what's valid and invalid in this scenario, but most importantly, we'd create quite a few automated tests to make sure this scenario keeps working."

    I come to you with a scenario, describing exactly what it is and what it is doing. You say it does not work, or that it has problems, but don't give any evidence why.

    "...but this use case isn't supported until Isomorphic says it is..."

    I got the message many replies ago. But the fact that it isn't supported doesn't mean it doesn't work or that it has problems.

    "So, if you want this work estimated, let us know."

    I approached Isomorphic before starting the thread, asking which way would be the best to handle this case. You, Isomorphic, pointed me to write a thread in the forum.
    Last edited by ssequeira; 29 Apr 2016, 05:21.

    Leave a comment:


  • Isomorphic
    replied
    The poc you did had also proxying in place, although you did it only for DSRequests. I was not part of the initial PoC scope nor acceptance, nevertheless, having the proxy for DSRequests accepted but not for the static files... seems a bit... hard to believe...
    There was no cross-browser way at the time to do cross-domain requests (outside of the <script> tag injection hack, which has security issues), so there was no other way to enable server communication. But we quite agree, as long as you *have* to do proxying for DSRequests, it makes sense to do proxying for static resources. However, your requirements were very clear on this, so we worked out a GWT compiler extension that enabled cross-domain loading.

    These days, you could securely do cross-domain DSRequests in all modern browsers, so the proxying could be completely eliminated. Which route to take depends on whether you're more comfortable with the extra infrastructure and performance penalties for proxying, vs the GWT compiler munging that was necessary to make cross-domain loading work (which might be simpler now - we haven't checked).

    Additionally, the way the inter app communication is solved is not the same way. Just compare the amount of boiler plate code your PoC has vs this.
    It's the same approach. Libraries for doing interapp communication did not exist 5 years ago, so the "boilerplate" you're referring to is just a PoC-level implementation of the same approach used by interapp.

    Also, Canvas.getById() didn't exist 5 years ago either. More on this below..

    "It's not valid to retrieve widgets created by a separately compiled application..."

    Why not? I just proved it is. Please beware I am interested in very low level manipulation, such as adding a layout to another layout. Nothing more, nothing less.

    "...and the way you are using it will lead to memory leaks, potential ID collisions on auto-generated IDs, and other problems."

    Care to expand on all 3 concerns?
    - why memory leaks and in which scenarios?
    - potential ID collisions -> yes (hmm, actually depends on how the IDs are generated). Can we introduce a mechanism to have the auto-generated ID's prefixed with module name?
    - which other problems?
    Canvas.getById() was designed for retrieving widgets created by Component XML, it assumes there is no other GWT application around that also has a reference to the underlying SmartClient widget. So when you retrieve a widget this way, you either create a duplicate SmartGWT wrapper for the underlying SC widget, or one GWT app tries to re-use the wrapper from another. The first would leak memory and/or break certain behaviors of the widget in the app that created it, the second would crash either at the typecast, or on subsequent invocations, because the method names are obfuscated differently. Which behavior happens probably depends on which version of SmartGWT you're using, because we've made changes over the years in how wrappers are allocated and tracked. It also depends on the mode you're running in (compiled vs SDM vs classic DevMode).

    This is why, to actually solve this problem for real, our PoC works at the JSNI level when coordinating on widgets and containment.

    Now, an upgraded variant of Canvas.getById() could be created that has features to coordinate between multiple separately-compiled applications, for example, detecting that a component was created in another application, tracking two or more wrappers objects from different applications, and making sure they get cleaned up correctly by coordinating through the single shared SmartClient runtime. But the current Canvas.getById() isn't designed to handle that, and is not supported for the usage you've tried.

    Big picture, you have this oddly belligerent tone throughout this thread, and you seem to think you have "proved" something, or that you are in an argument. You aren't. When you run into the issues we've explained with your current approach, you can't validly file issue reports with us, because this use case is not one we currently support. If we wanted to actually support this use case, we'd need to make a variety of different changes and set up a few new APIs, create docs describing exactly what's valid and invalid in this scenario, but most importantly, we'd create quite a few automated tests to make sure this scenario keeps working.

    In a nutshell - you could spend time replicating the PoC we built for you in a hundred different ways, but this use case isn't supported until Isomorphic says it is, and we only say something is supported when we've got a clearly correct approach, documented, with autotests. So, if you want this work estimated, let us know.

    Leave a comment:


  • ssequeira
    replied
    The poc you did had also proxying in place, although you did it only for DSRequests. I was not part of the initial PoC scope nor acceptance, nevertheless, having the proxy for DSRequests accepted but not for the static files... seems a bit... hard to believe...
    Additionally, the way the inter app communication is solved is not the same way. Just compare the amount of boiler plate code your PoC has vs this.

    "It's not valid to retrieve widgets created by a separately compiled application..."

    Why not? I just proved it is. Please beware I am interested in very low level manipulation, such as adding a layout to another layout. Nothing more, nothing less.

    "...and the way you are using it will lead to memory leaks, potential ID collisions on auto-generated IDs, and other problems."

    Care to expand on all 3 concerns?
    - why memory leaks and in which scenarios?
    - potential ID collisions -> yes (hmm, actually depends on how the IDs are generated). Can we introduce a mechanism to have the auto-generated ID's prefixed with module name?
    - which other problems?
    Last edited by ssequeira; 28 Apr 2016, 06:40.

    Leave a comment:


  • Isomorphic
    replied
    It looks like you've solved the easy problem (inter- app communication) in the same way we did in the POC 5 years ago, but not either of the non-trivial problems, which are:

    1. cross-domain loading - at the time of the POC we built, this required either a GWT compiler extension plus post-compilation munging of files, or a proxying solution along the lines of what you've mentioned. However the proxying solution, which we brought up at the time, was ruled out explicitly by your requirements. It's great if you are now willing to use a proxying approach, as cross-domain loading is one of the main ways in which core GWT technology created large impediments to this kind of "hybrid" application.

    2. coordination of resources between two separately compiled apps - Canvas.getById(), which you use to retrieve a widget created by another application, is valid for use with widgets created by the same application, or with widgets created by Component XML. It's not valid to retrieve widgets created by a separately compiled application, and the way you are using it will lead to memory leaks, potential ID collisions on auto-generated IDs, and other problems.

    Leave a comment:


  • ssequeira
    replied
    This illustrates exactly what I was after.
    At this point in time this solution leverages only the client side.
    Note that there is only one server running. Both portal and pl1 modules are served by it.
    Ultimately the pl1 module could be served by another container (this is the goal), at which point a proxy should be put into place to guarantee that the client "sees only the portal server", bypassing cross domain problems.
    All datasource calls can also be proxied. In fact smartGWT provides an http proxy servlet which can be used for this purpose.

    The projects use smartGWT power edition 3.1-p20151015
    If you have another version change it in:
    index.html
    pom.xml

    Yesterday I tried a different approach, which is instead of using an event bus directly exposing a JAVA method to JavaScript, and have this method called by another module. http://www.gwtproject.org/doc/latest...I.html#calling

    Which approach is better, Method invocation or event bus is beyond the point of the PoC, but it is worth mentioning that method invocation also works, but has the drawback that you need to know the name and signature of the JavaScript function exposed by the different modules. This would have to be agreed in advance between the different teams.

    -----------------------
    pre requisites

    1. maven
    2. java 8
    3. eclipse
    4. smartgwtpower 3.1p.2015-10-15

    -----------------------
    how to

    1. unpack to a folder of your choice
    2. run 'mvn clean install' on the parent folder (distributed_poc)
    3. open portal project in eclipse (import general project)
    4. edit server.properties and change webRoot: /full_path_from_folder_of_point_1/portal/src/main/webapp
    5. run PortalApp.java
    6. open google chrome on http://127.0.0.1:8080/index.html (chrome/safari only, if you want support for other browsers edit the gwt.xml files and remove the line
    <set-property name="user.agent" value="safari"/>. This was put in place to reduce the GWT compilation time.)


    https://goo.gl/tjZtOi

    Leave a comment:


  • ssequeira
    replied
    I will be posting a solution soon, with example projects that can be run easily for whomever is interested in it.
    It is based on https://github.com/sambathl/interapp-eventbus and works like a charm, with smartGWT.
    Stay tuned.

    Leave a comment:


  • Isomorphic
    replied
    Can't scribbling into each other's DOMs be layout management? How come?
    It's either possible or not. Seems from your answer it is both at the same time.
    Unfortunately it's as simple as you are hoping. Two separately compiled GWT applications are in a situation analogous to two widgets or UI frameworks from different vendors - they have totally different internal workings. You can have one framework write into a designated spot in a DOM that was created by the other framework, and that's the approach used to, for example, embed CKEditor inside a SmartClient Layout. However, when you do this, all of the coordination that would normally happen between two widgets from the same framework (notifications of size changes, creation/destruction, focus and tab index management, etc), has to be manually coordinated between the two frameworks. For a good overview of the issues involved, see our DOM Integration docs. As you'll see, this overview ends by pointing out that certain problems like tab index coordination for accessibility and multi-level modality are hard enough to be effectively intractable.

    Robert Keane's Turduckeon sidesteps a lot of this by assuming each GWT application occupies it's own tab. This creates a minimum of necessary coordination since each application's widgets take over most of the screen when the application is active. The portal interface you wanted, on the other hand, requires a maximum of coordination between UI from different applications - there's a lot of complex auto-sizing, drag and drop, and dynamic creation and destruction going on. This is why we say it's really only feasible with SmartGWT, where the underlying widgets from two different GWT applications are all SmartClient widgets, and already coordinate correctly in all the required ways.

    Coming back to the solution you provided, an example of maturity could be the inclusion of JSInterop. This actually drops a bomb in your argument "That can't be done as each application has separately obfuscated code."


    JSInterop doesn't solve the problem above. With JSInterop or many other approaches, you could make it possible for one GWT application to call APIs in another. However, if you try to pass a Panel from one application as a new child of a Panel from another application, all the methods the parent Panel expects to use on its child, and the methods the child expects to call on its parent, are all obfuscated under different names.

    So, at best, you'd have fork GWT widget code, go through and externalize every single API that might be called with any GWT widget. It's not clear that even this would work.

    Can you please provide references from the GWT team and GWT project contributors on the topic of "...people from the GWT team and contributors have commented that this pattern of loading multiple GWT applications into one page is not something GWT intends to support, or is deprecated, and so forth."


    This is our impression from years of reading GWT forums, and in particular from various threads we hit when trying to work around GWT issues that prevented cross-domain loading (as you also required). We don't have the individual references, sorry. Feel free to replicate this research on your own.

    Leave a comment:


  • ssequeira
    replied
    "It's also not clear what he means by showing GWT components from different GWT apps nested together, because that doesn't actually work. How you are going to do a cross-module call to add a component to a Panel created by another module? That can't be done as each application has separately obfuscated code."

    "At best, the different GWT modules could scribble into each other's DOMs, but not directly participate in layout management."

    Can't scribbling into each other's DOMs be layout management? How come?
    It's either possible or not. Seems from your answer it is both at the same time.

    "Also, in case you misunderstood - Keane's presentation promotes the same solution we created for you (an inter-app event bus)."

    I understand perfectly. That's why I pointed you to the presentation, remember?

    Well, at least we can agree I am not alone pursuing this. At least some products from Google have the same issue. And I can imagine many others. They might be dealing with it today using different approaches (and surviving, like we do). These approaches are mainly related to project management and carefully release coordination between multiple teams. But in an enterprise environment there is a tipping point where this is not possible anymore. We reached it are looking carefully at alternatives on how to overcome this problem while keeping the technologies we have in place. If not possible...

    Coming back to the solution you provided, an example of maturity could be the inclusion of JSInterop. This actually drops a bomb in your argument "That can't be done as each application has separately obfuscated code."

    Can you please provide references from the GWT team and GWT project contributors on the topic of "...people from the GWT team and contributors have commented that this pattern of loading multiple GWT applications into one page is not something GWT intends to support, or is deprecated, and so forth."

    Blama the topic of the presentation given by Robert Keane was on how to leverage the management of a seemingly single application (one page in the browser, no reloads) which is built by multiple teams. Each team is responsible for a separate functionality on the application, and they might want to release updates to those functionalities without having to wait for a release of the whole application. Compilation time plays a minor role here, in the sense that you get it out of the box, because as soon as you can "modularize" the application in such a way then if you are part of a team responsible for a specific feature you can just open your specific project and work/compile that feature without having to compile the whole code of the application. Modularization in the sense of breaking down an application in different modules is possible already today, what is not possible is the ability to release these modules independently. Today you still need a single GWT application which inherits all those modules and if you want to release a new feature of a specific module you need forcibly to make a release of the GWT application.
    The idea is that you could deploy the modules stand alone (so they have their own release cycle) and then have the "application" use the functionality in these remote modules.
    This is what is depicted in the picture on my first post.
    Hope this clarifies the use case.
    Last edited by ssequeira; 22 Apr 2016, 07:49.

    Leave a comment:


  • Blama
    replied
    Hi all,

    I read the GWT.create slides and it begins with the problem description: Compile times in multi million LOC applications.
    I'm far away from this, but isn't this a non-problem anymore in 2016 with GWT 2.7 and SuperDevMode incremental compile, making the whole pattern obsolete (at least for new applications)? The advantage is now available for free without the severe disadvantages you mentioned.
    I'm still using FF26 DevMode, but when I tried SuperDevMode incremental compile was working.

    Best regards
    Blama

    Leave a comment:


  • edulid
    replied
    Do you have a link to the solution you proposed?

    Leave a comment:


  • Isomorphic
    replied
    Robert Keane works at Google but not on the GWT team. On the other hand, over the years, people from the GWT team and contributors have commented that this pattern of loading multiple GWT applications into one page is not something GWT intends to support, or is deprecated, and so forth.

    So again our advice is to carefully consider whether it makes sense to pursue this design given that the actual GWT team has been anywhere from indifferent to hostile toward it in the past.

    Also, in case you misunderstood - Keane's presentation promotes the same solution we created for you (an inter-app event bus). However, he glosses over a *lot* of details. Making it work at all for you required compiler extensions.
    It's also not clear what he means by showing GWT components from different GWT apps nested together, because that doesn't actually work. How you are going to do a cross-module call to add a component to a Panel created by another module? That can't be done as each application has separately obfuscated code.

    At best, the different GWT modules could scribble into each other's DOMs, but not directly participate in layout management. Our solution actually allowed true cross-module participation in layout management, as well as shared data resources, which again, is impossible without SmartGWT.

    In light of all of the above, please revisit your "alarmingly bad" comment. We really do understand the issues here, whereas you've just read a slideshow and not actually implemented this.

    Leave a comment:


  • ssequeira
    replied
    the level and content of your response is alarmingly bad.
    it feels as if you don't even understand the problem. you didn't at first and seem to fail to understand it again now.
    in such cases asking for more details helps, instead of dismissing the situation just because you don't support it.

    not supporting it does not necessarily mean it is bad or wrong.
    I advise you to actually go back to 2013 and review what the people from Google (you know, the folks behind GWT) have presented in GWT Create conference.

    http://www.slideshare.net/RobertKean...multiple-teams
    Last edited by ssequeira; 21 Apr 2016, 03:31.

    Leave a comment:

Working...
X