Announcement

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

    multiple smartGWT applications under one portal

    Hello.
    A few years back we have worked together in a concept which would allow multiple smartGWT applications developed independently to be combined under a single portal.
    The portal would be a smartGWT application itself. The portal would show different links or buttons which when clicked would trigger a screen from another smartGWT application, deployed somewhere else under the same domain, to be displayed seamlessly on the portal.
    Click image for larger version

Name:	main portal - multiple smartgwt apsp.png
Views:	408
Size:	105.7 KB
ID:	237169
    I would like to know if during these years you have matured this concept and if the newest versions of smartGWT already allow such a construct out of the box.

    Thank you.

    #2
    We recall this application - the problem being solved was not a portal per se but actually the requirement of having multiple separate browser frames / windows communicating, whereas in typical portals, all content is loaded into a single browser frame and all content plays by special rules that allows it to cooperate.

    The idea of instead creating a portal out of several browser frames is still considered a poor architecture and not one that any other customers have pursued. There is nothing really to "mature" about the solution we provided - doing things this way is inherently complex, and the approach we provided was the best available, and still is the best available.

    Comment


      #3
      I am not sure we are referring to the same problem/context.

      The problem I am trying to solve is not having multiple separate browser frames / windows communicating.
      There will be only one frame / window. The content of this frame / window would come from different sources (smartGWT JS files. After all from client side perspective a smartGWT app is just a bunch of static files, including the module's JS file).

      If the portal would be written with plain JS this could be achieved: the content would be able to cooperate, even with functions coming from different JS files.
      Since smartGWT is "just" a wrapper for JS (in the context of client side only) one would suppose this to be achievable as well using smartGWT.

      The process to achieve it today with smartGWT, using the solution you provided is not inherently complex, but rather rough; in the sense that there are a couple of things that could be hidden from the "API", or at least moved to a lower level layer. That's what I meant by "mature", in the context of the problem and solution provided.

      Again there are no multiple frames or windows involved here.
      There is one frame / window, the content which populates it and the interaction between the different content is described in multiple JS files instead of one.

      Would appreciate if you can confirm that this is the application/context you had in mind.

      Comment


        #4
        Ah, the problem being solved was actually loading multiple, separately compiled GWT applications into a single browser frame and having them work as a portal. However, the gist of the response still holds: the problem is that GWT assumes a single compiled application takes over the entire page. Code in separately compiled GWT applications is separately obfuscated and cannot communicate directly; it can only communicate by going through a JavaScript intermediary layer and passing data around. This style of communication is similar to what's required to communicate between separate browser frames, in fact, in some ways multiple frames would be easier!

        SmartGWT is the only GWT-based technology that could make what you want possible at all - it's not possible in any framework that uses GWT's core widgets.

        As far as the situation today, GWT continues to take as a basic assumption that only one compiled GWT app will exist in a page, and you continue to be the only customer that has asked us to try to work around this.

        Here again, there's nothing to "mature" in our design - it works in the way it has to. As the far as the API seeming "rough", we did a POC for you and took it exactly as far as requested. This is not a product feature (and we have no plans to make it one) so nothing has changed in the meantime.

        It would be possible to build extensions to the GWT compiler to make it easier to make cross-application calls in GWT, by causing the compiler to generate additional JavaScript code triggered by annotations that you would add to certain method calls that need to go between GWT applications. If you want us to think through the details of this and show you how the resulting code might work, contact our Consulting team to get started. However bear in mind, core GWT is somewhere between indifferent and actually hostile to your proposed use case. Changes in future versions of GWT could plausibly make the whole thing impossible just as Isomorphic finishes making it easier on current versions of GWT.

        Comment


          #5
          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.

          Comment


            #6
            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.

            Comment


              #7
              Do you have a link to the solution you proposed?

              Comment


                #8
                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

                Comment


                  #9
                  "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.

                  Comment


                    #10
                    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.

                    Comment


                      #11
                      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.

                      Comment


                        #12
                        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

                        Comment


                          #13
                          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.

                          Comment


                            #14
                            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.

                            Comment


                              #15
                              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.

                              Comment

                              Working...
                              X