1 2 Previous Next 17 Replies Latest reply on Jul 5, 2011 4:51 PM by rbattenfeld

    WebAppDescriptor API proposal


      Hi Andrew and all others


      I created a new discussion about the WebAppDescriptor API. The titel is more accurated.


      I am stepping into this task of creating an API for the webAppDescriptor. I first analyzed a little bit the schema files and as well the current API implementation. I think, the API design should follow how the specification is designed. This helps to make the API consistend with the spec.


      What do you think about the following package names:

      org.jboss.shrinkwrap.descriptor.api.javaee6                   // javaee_6.xsd

      org.jboss.shrinkwrap.descriptor.api.webapp30               // web-app_3_0.xsd

      org.jboss.shrinkwrap.descriptor.api.webcommon30        // web-common_3_0.xsd

      org.jboss.shrinkwrap.descriptor.api.jsp22                      // jsp_2_2.xsd



      In the packages are the interfaces placed as defined in the corresponding schema, meaning the complex types. For example, the WebAppDescriptor.java is in the webapp30 package and so on. This allows to implement all other xsd schemas having dependencies for example on the web-common schema.


      I prototyped a little bit and have implemented the child interface as you have suggested. Cool. Here is a code snippet:


      final String webApp = Descriptors.create(WebAppDescriptor.class)






      Note the double step back from auth-contraint to security-contraint to web-app.


      This would create the following web.xml file:


      <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"


          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">





















      Does the proposal reflect your idea of the API design? Let me know what you think and I will change it.






        • 1. WebAppDescriptor API proposal

          This looks very good.



          Ralf Battenfeld wrote:

          What do you think about the following package names:

          org.jboss.shrinkwrap.descriptor.api.javaee6                   // javaee_6.xsd

          org.jboss.shrinkwrap.descriptor.api.webapp30               // web-app_3_0.xsd

          org.jboss.shrinkwrap.descriptor.api.webcommon30        // web-common_3_0.xsd

          org.jboss.shrinkwrap.descriptor.api.jsp22                      // jsp_2_2.xsd



          That seems pretty intuitive to me.  We need to account for different schema versions.  Previously we'd discussed putting each in a different module, but I think this makes more sense.


          Do you have a pull request or repo/branch out somewhere?  Also I probably never pointed you to the ShrinkWrap Dev instructions, so for reference:


          ShrinkWrap | Development and Contribution




          • 2. WebAppDescriptor API proposal

            Thanks Andrew


            So I will continue.


            Yes, I have already a fork on the descriptor project. I have already checkin some stuff because I work sometimes in the office and also at home on this project. GitHub is just perfect for doing that. But I am not sure that I am in line with the instructions. For example, I didn't branch the fork. If something is wrong, then I will simply create a new fork and will move the code to the new fork which is then compliant with the instructions.


            My git url is: git@github.com:ralfbattenfeld/descriptors.git


            I worked a litle bit further. I created a little xsl script for creating interface stubs out of a given schema file. THe reason for this is, I am conserned a little bit about the complexity, meaning to cover all types and possibility. It is very easy to make mistakes here. So, i think this little script helps not to forgot the details And it is reusable.


            Thanks for the comment about the other discussion. I also think this is good to have. I could think of something thing like this:


            final String webApp = Descriptors.create(WebAppDescriptor.class)






            I will update what I have done so far but it is not completed. I hope to be on the right side




            • 3. Re: WebAppDescriptor API proposal

              I think the API looks very good, quite impressive actually. I think a package structure for each schema + version is sufficent, rather than have them in separate modules.

              • 4. WebAppDescriptor API proposal

                Thanks Tommy. I will complete creating the API and have then to check it against the specification. There will be for sure something to adjust and to correct. If Andrew is also happy with this, then I can go further. It is anyway a good exercise for me.

                • 5. Re: WebAppDescriptor API proposal

                  Does this mean that each Descriptor will be mapped to one and only one version?






                  This will reder the current descriptor.version("") somewhat pointless. Unless we change version to behave more like a upgrade / downgrade feature. e.g:



                  org.shrinkwrap.....webapp25.WebAppDescriptor = Descriptors.create(org.shrinkwrap.....webapp30.WebAppDescriptor.class)
                            .version(org.shrinkwrap.....webapp25.WebAppDescriptor.class) // map the 3.0 version down to how 2.5 was
                  • 6. Re: WebAppDescriptor API proposal

                    Was the previous idea to provide a WebAppDescriptor for all versions?


                    The version is probably still useful, Tommy suggested to be able to override all fields.


                    I am not sure if I have done too much in advance. If yes then I have no problem to throw it away or to change everything.


                    Here is a preview how the API could look like. My idea was to provide a similar way of defining the descriptor as when you define via an xml editor with ode completion:


                    final String webApp = Descriptors.create(WebAppDescriptor.class)













                                   .asyncSupported(false) /* DescriptionGroup is missing */

















































                                   .location(23, "")

                                   .location("", "")






















                    //               .authMethod(AuthMethodType.BASIC) --> TODO
























                    • 7. Re: WebAppDescriptor API proposal

                      Well, the current version supports setting the schema version, but is does not change the API version used. And of course, having the API support all versions are some what impossible.


                      I'm not sure if the effort is worth it, but making the common elements between the versions the same type could make sense, e.g.


                      webapp25.Servlet extends webapp.Servlet
                      webapp30.Servlet extends webapp(30?).Servlet


                      Some consumer might handle Servlet in a more general way and not having to care about the specific versions.


                      Splitting packages based on xml schemas, I guess WebApp and WebAppFragment are now sharing the same Types ? (they do share most XML elements/types)


                      Direct mapping to xml looks good, but a bit more verbose then necessarily in some cases. It's not 100% clear where the bounderies for Descriptors are. Is it a pure object struct to xml struct mapping ? Can we change the Object model to better suite our usage? How about convinience methods ?


                      Just some of the top of my head(most taken from the old version) e.g:


                      short cut for:
                                webapp.servlet(mySerlvetClass.getSimpleName(), myServletClass.getName())
                                          webapp.servletMapping(myServletClass.getSimpleName(), mapping)
                      (similar for Filter) 
                      webapp.servlet(Class<?> myServletClass, String... mappings)
                      shortcur for:
                      WelComeFiles welcomes = webApp.welcomeFileList()
                      webapp.welcomeFiles(String... files)
                      In some cases we can eliminate the need to use .up()
                      webapp.errorPage(404, "myerror.jsp")
                      webapp.errorPage(SecurityException.class, "myerror.jsp")
                      webapp.mimeType("text/plain", "some")
                      webapp.absoluteOrdering(String... useArrayOrder)
                      webapp.contextParam("name", "value")
                      The Object model could model the relationship between Servlet and Servlet Mapping as one thing
                      (same with Filter)
                      webapp.getServlet(String name).getServletMappings()



                      ps: Ralf, this is not critique to your model, just trying to open up the discussion.

                      • 8. Re: WebAppDescriptor API proposal

                        Hi Aslak


                        Yes, open discussion is good My fear is that you and the current contributers may think that I don't respect the existing work. It is exactly the opposite!


                        After one week digging into this, I think the following:

                        • The descriptor project is something which I think is required for shrinkwrap
                        • The various deployment descriptors are complex and a manual approach of designing neither the API nor the Impl is with an acceptible work load possible. I assume that we whant to provide a full API.
                        • But I think it is fairly simple to generate the API and Impl classes. I think,a simple xsl script (I started with such a script) which exactly produces the API and hopefully the Impl classes in the form we want. So, I believe, one particular API is producable within 1 hour,probably the same for the impl classes. When the script is ready
                        • I think a clear separation between the proposed packages is good. The schemas already share reusable types all over the place.
                        • I would stick into distinct descriptor versions and to mix that.


                        The current proposal of the API is just following what the spec defines. It is no problem to make it more usable in the way you propose.


                        So, I'd suggest to automate the API and the Impl class generation as much as possible.


                        - Ralf

                        • 9. Re: WebAppDescriptor API proposal

                          So, I forgot to mention that we could provide both, an generated API and additionally more convinient overloaded methods in the way you have suggested. As the current version provides.

                          • 10. Re: WebAppDescriptor API proposal

                            Hi Aslak


                            I think your suggestions are definetly good and we should address it. My vision is something which follows some rules so that every descriptor is following the same principles. That is the reason why I try to standardise the API. But I think there is a simple solution to combine both.


                            I think of a kind of API facade that allows to customize the internals. I probably didn't explain my ideas good enough e.g generating etc


                            Does someone have another idea? As Aslak said, let's discuss the descriptor API.


                            Thanks again for your input.



                            • 11. Re: WebAppDescriptor API proposal

                              Hi all


                              I'd like to update with my activities done in the last couple of days.


                              I realized that I have to change the xsl processing slightely. I implemented a pre step before creating the interfaces and enums. This pre transformation creates a xml file called 'metadata.xml'. It parses all java ee 6 related schema files and produces metadata informations like data types, enums and classes.


                              So, I believe that this pre step makes the next transformation pretty simple. If you like, you can have a look in the ../impl/src/main/resources/dd folder


                              I also thought about Aslak's suggestions. I will include these suggestions as much as possible. This means:

                              • introducing setters and getters
                              • if a argument is of type class then additionaly the class type can be defined in the method
                              • if a single argument is defined as maxOccurs="unbounded"/> then the method is defined using var args like foo(String ... names)
                              • if possible, combinations of xsl:choose and xsl:element are resulting in foo(option1, element) and foo(option2, element)


                              I also think of introducing a iterator interface so that a created deployment descriptor can be traversed back and forth.


                              Andrew and Aslak and probably others too, are busy with the next release and I will not disturb these guys and will just go forward.




                              • 12. Re: WebAppDescriptor API proposal

                                Just had some thought on the API design last night, hacked up a little demo.


                                Basically i'm not a to big of a fan of the .up() method on the sub types. The problem we're having is of course it's hard to chain a hierarchical model, so... What is we break it up instead. We can chain the individual levels, but we add them together in a more traditional way.


                                going from:














                                We can reuse the Type information we have and make 'generic' add methods pr level. So instead of having, filter() servlet(), we can flip it and say, add(Filter), add(Servlet), Collection<Servlet> get(Servlet)


                                WebAppDescriptor then becomes add(WebAppSubType) + what ever special convenience methods we want to add for e.g. name, error(page, msg) etc



                                (ps don't look to closly on the generics and interfaces here)

                                • 13. Re: WebAppDescriptor API proposal

                                  Full chat last night with Ralf:



                                  (07:29:49 PM) ALR: Hi/
                                  (07:29:53 PM) ALR: Today's topic:
                                  (07:29:56 PM) ALR: Descriptors
                                  (07:30:00 PM) ALR: Status update, rbattenfeld?
                                  (07:30:01 PM) ALR:
                                  (07:31:00 PM) rbattenfeld: I am able to present a first version of the web app deployment descriptor. This dd is fully generated
                                  (07:31:44 PM) rbattenfeld: Some little things are missing
                                  (07:32:04 PM) rbattenfeld: but enough for a preview
                                  (07:33:05 PM) ALR: rbattenfeld: Link?
                                  (07:33:29 PM) rbattenfeld: the link is: git@github.com:ralfbattenfeld/descriptors.git
                                  (07:33:54 PM) ALR: From your master?
                                  (07:34:00 PM) rbattenfeld: yes
                                  (07:34:17 PM) ALR: Pulled it in.
                                  (07:34:19 PM) ALR: Building.
                                  (07:35:34 PM) rbattenfeld: I hope it works... I submitted just some minutes ago the last peace
                                  (07:35:41 PM) ALR: Build worked great
                                  (07:35:51 PM) ALR: Bringing into IDE
                                  (07:37:57 PM) rbattenfeld: You can find two test classes. One for the web30app and one for the application6 descriptor. Both are located in the impl folder
                                  (07:41:14 PM) ALR: OK
                                  (07:41:15 PM) ALR: Got 'em.
                                  (07:42:03 PM) ALR: rbattenfeld: WebApp30Descriptor<T> is genericized?
                                  (07:42:17 PM) ALR: What's the expected end-user view?
                                  (07:43:42 PM) rbattenfeld: What you mean with end-user view?
                                  (07:43:52 PM) ALR: Hehe
                                  (07:43:58 PM) ALR: End-users are the coders.
                                  (07:44:00 PM) ALR: So the API.
                                  (07:44:18 PM) ALR: For instance in the test we've got:
                                  (07:44:18 PM) ALR:  final WebApp30Descriptor web = Descriptors.importAs(WebApp30Descriptor.class).from(
                                  (07:44:18 PM) ALR:             source);
                                  (07:44:44 PM) ALR: Now, WebApp30Descriptor is expecting to have the generic context closed somewhere.
                                  (07:44:49 PM) ALR: In this case, by the user
                                  (07:44:51 PM) ALR: Like:
                                  (07:45:25 PM) ALR: final WebApp30Descriptor<SomeType> web = something;
                                  (07:45:37 PM) ALR: Can we really accept any type in there?
                                  (07:45:53 PM) ALR: Or is the intent for all types "T" to really return the current type used?
                                  (07:45:59 PM) ALR: rbattenfeld: ^
                                  (07:46:32 PM) rbattenfeld: The type T is used for the jump back as you asked for
                                  (07:47:06 PM) ALR: BTW aslak had some prototype ideas there.
                                  (07:47:10 PM) ALR: Which we can get to in a bit
                                  (07:47:17 PM) ALR: Which avoid the need for "up"
                                  (07:47:30 PM) ALR: rbattenfeld: But let's see:
                                  (07:47:35 PM) ALR: When I invoke:
                                  (07:47:45 PM) ALR: final WebApp30Descriptor<SomeType> web = something;
                                  (07:47:57 PM) ALR: web.distributable();
                                  (07:48:04 PM) ALR: ...what type am I expecting to return?
                                  (07:48:12 PM) ALR: Do you see where I'm going with this?
                                  (07:48:28 PM) ALR: As it stands, the *user* is saying what type he'll get back, and "T" is open-ended.
                                  (07:48:35 PM) ALR: A user can put anything in there.
                                  (07:49:00 PM) rbattenfeld: Yes, just a moment, i will look for something
                                  (07:49:40 PM) ALR: final WebApp30Descriptor<Exception> web = Descriptors.importAs(WebApp30Descriptor.class).from(source);
                                  (07:49:40 PM) ALR: final Exception e = web.distributable();
                                  (07:49:48 PM) ALR: See? 
                                  (07:50:03 PM) ALR: web.distributable doesn't really return Exception.  But I just told the compiler it does.
                                  (07:50:56 PM) rbattenfeld: THis throws an exception?
                                  (07:51:03 PM) ALR: Of course not.
                                  (07:51:16 PM) ALR: I could say WebApp30Descriptor<String> web;
                                  (07:51:18 PM) ALR: Just as easily.
                                  (07:51:52 PM) rbattenfeld: Ok I understand
                                  (07:51:52 PM) ALR: rbattenfeld: Let me ask this another way:
                                  (07:51:58 PM) ALR: What *is* T?
                                  (07:52:32 PM) rbattenfeld: T represents the parent node of a particular child node
                                  (07:52:42 PM) ALR: Perfect.
                                  (07:52:57 PM) ALR: rbattenfeld: What is the parent node of WebApp30Descriptor ?
                                  (07:53:28 PM) rbattenfeld: there is no parent node. It is the root node
                                  (07:54:07 PM) ALR: OK.  So why not declare instead of:
                                  (07:54:09 PM) ALR: public T distributable();
                                  (07:54:11 PM) ALR: use:
                                  (07:54:25 PM) ALR: public WebApp30Descriptor distributable();
                                  (07:54:27 PM) ALR: ?
                                  (07:55:17 PM) rbattenfeld: Actually, this is the idea...
                                  (07:59:44 PM) ALR: ..?
                                  (08:00:05 PM) ALR: These tests look nice.
                                  (08:00:15 PM) ALR: In the jboss-metadata ones we usually have an "all" resource
                                  (08:00:23 PM) ALR: Like web.xml with *every* element possible
                                  (08:00:29 PM) ALR: And then we can parse/pull of that
                                  (08:00:31 PM) ALR: *off
                                  (08:01:16 PM) rbattenfeld: The reason why the type T is required, is some nodes are used in many places and must somehow able to return to different parents. For example all classes defined by the javaee6 spec
                                  (08:02:36 PM) ALR: rbattenfeld: OK.  But for any known type, don't you as author know the type to be returned for the entire hierarchy under WebApp30Descriptor?
                                  (08:03:58 PM) rbattenfeld: You mean, is the class used only once?
                                  (08:04:03 PM) ALR: rbattenfeld: Nope.
                                  (08:04:15 PM) ALR: To be reused in different hierarchies is why we have generics.
                                  (08:04:21 PM) ALR: So you *can* facilitate that reuse.
                                  (08:04:34 PM) ALR: However, we've leaked the generic context out to the user here.
                                  (08:04:41 PM) ianbrandt left the room (quit: Quit: ianbrandt).
                                  (08:04:52 PM) ALR: Because WebApp30Descriptor is the user view, and the generic context is not yet closed.
                                  (08:05:00 PM) ALR: Am I being clear?
                                  (08:05:05 PM) rbattenfeld: Yes, I aggree
                                  (08:05:23 PM) ALR: I have a good example of this; one sec:
                                  (08:06:48 PM) ALR: rbattenfeld: https://github.com/shrinkwrap/shrinkwrap/blob/master/api/src/main/java/org/jboss/shrinkwrap/api/container/ClassContainer.java#L33
                                  (08:07:00 PM) ALR: OK, that's a ClassContainer.  Anything capable of *containing* a class.
                                  (08:07:25 PM) ALR: We don't know what the target type is yet.  Because lots of things can contain a class, and we wanna reuse this definition.
                                  (08:07:58 PM) ALR: So we don't really expect users to use ClassContainer directly.
                                  (08:08:06 PM) ALR: They should get it via some other means.
                                  (08:08:08 PM) ALR: Enter: https://github.com/shrinkwrap/shrinkwrap/blob/master/api/src/main/java/org/jboss/shrinkwrap/api/spec/JavaArchive.java#L34
                                  (08:08:16 PM) ALR: JavaArchive closes the generic context
                                  (08:08:39 PM) ALR: (ServiceProviderContainer there extends ClassContainer as well)
                                  (08:08:54 PM) ALR: And thus the user has no burden of handling the generics.
                                  (08:09:05 PM) rbattenfeld: Ok. I got it. I can refactor it in this fashion
                                  (08:09:14 PM) ALR: rbattenfeld: Super.
                                  (08:09:35 PM) ALR: rbattenfeld: So, I had the idea of "up()"
                                  (08:09:45 PM) ALR: rbattenfeld: Aslak suggested another mechanism:  https://gist.github.com/1025597
                                  (08:09:58 PM) ALR: 2 different approaches
                                  (08:10:05 PM) ALR: His uses more factory methods
                                  (08:10:07 PM) rbattenfeld: Yes, this was your idea
                                  (08:10:22 PM) ALR: Well, "up()" I think was mine.
                                  (08:10:26 PM) ALR: This one here is his.
                                  (08:10:39 PM) ALR: So the usability of each is something we should discuss more.
                                  (08:10:52 PM) ALR: When we're all here.
                                  (08:11:03 PM) ALR: rbattenfeld: Also...can you explain to me the function of the "gen" module?
                                  (08:11:14 PM) ALR: Like, what's generating those classes?
                                  (08:11:26 PM) ALR: Not the build, is it?
                                  (08:12:08 PM) rbattenfeld: Yes, I generated the classes in the gen module via two xslt scripts
                                  (08:12:35 PM) ALR: rbattenfeld: And that's in the build, not outside, right?
                                  (08:12:56 PM) rbattenfeld: and move it later manually to the API and IMPL folder as long as there this is not a agreed solution
                                  (08:13:23 PM) ALR: So it's a tool.  How to run it?
                                  (08:14:02 PM) rbattenfeld: I wanted to include the transformation in maven but I didn't had the time so far to implement it.
                                  (08:14:25 PM) rbattenfeld: At the moment, the transformation is executed via editor
                                  (08:15:06 PM) ALR: Can I do it?
                                  (08:15:12 PM) ALR: Or requires some other tools I don't have?
                                  (08:15:33 PM) ALR: (In other words, looking to doc this so everyone working on it can benefit from the work you've put in here)
                                  (08:16:51 PM) rbattenfeld: Yes, I agree completely. I should have a readme somewhere that explains you the start the transformation. It comes asap


                                  • 14. Re: WebAppDescriptor API proposal

                                    Nice demo Aslak. I guess the discussion is continuing on https://gist.github.com/1028220. Is there any project page or similar available yet where one could read som more about how the project is defined etc? It would be great if there are some documentation available on the work done so far.

                                    1 2 Previous Next