Skip to Content

The concept of reusability plays a very important role in the Web Dynpro Framework. The so called pyramidal structure, where the model components are situated at the bottom of the pyramid and the application itself somewhere on top, has became quite popular, since it was first shown on the TechEd some time ago. However to refresh your memory I’ve tried to rebuild something that should look like the original:)

 

image

 

As you probably well know, all of the above components have their public parts, which can be reused throughout the pyramidal structure. A Web Dynpro Component without a public part is an isolated component that can only consume other components as Used DCs, but never serve as a basis for further reusability. So following this rule one can expect to have a great reusability for the model components and a rather small to none at all for the application on top.

 

If only everything was always so simple to be separated in such component categories, but it isn’t. It could happen that a certain component also has a visual interface that is quite practical to use in other components. Let’s check the following scenario – we have one source/model component that generates our data (no matter where the data comes from, could be RFC, Web Service or even EJB). This component has a view interface that shows all data that is retrieved from the backend. Let’s call this component “Source 1”. Additionally we have a second component that is both a source and a consumer. It consumes methods from “Source 1” and also uses the predefined visual interface from “Source 1”. Using the data provided, this component calculates some additional information and also shows it on the screen together with the visual interface of “Source 1”. Let’s call this component “Source 2”. Finally we have a third component that is a pure consumer. It simply uses methods from both “Source 1” and “Source 2” and shows on screen their visual interfaces plus some additional information on the selected record. On the following figure you can see the results of calling all 3 components:

 

image image image

 

To visualize the whole scenario, please take a look at the following figure:

 

image

 

The picture contains the word “Problem”, because there is such. It consists of the fact that calling the methods of “Source 1” over the “Source 2” interface does not populate the visual interface of “Source 1” with data and all we end up is a display of the visual interface of “Source 2” showing the correct calculations (based on data from “Source 1”), but we are not able to see the data itself, since the context nodes in “Source 1” were not populated with data. To do so, we need an additional call from our “Consumer” to “Source 1” and only after this call we can see the tabular data that “Source 1” contains. This however is a really redundant approach, since we end up calling twice the same method in “Source 1” – one time indirectly over “Source 2” and one time directly from “Consumer”. Before I bring in some more screenshots of the components to clear things up, I would like to show you – how the solution should look like:

 

image

 

As you can see, our task would be to eliminate the redundant call to “Source 1” and try to provide all information from “Source 1” to “Consumer” over the “Source 2” interface. What we achieve is a mere of 2 times load time reduction and spare one backend call per user. I guess it’s worth it, so let’s get on to it.

 

The next step is to review how the 3 components look like. We’ll start with “Source 1”:

 

image

 

As simple as it gets, we have our component controller that serves as a dummy data generator with the following function:

 

public void fillPeople( ){
    //@@begin fillPeople()
    //this.msgManager.reportSuccess("fill people preanalyze");
    int peopleSize = 5;
    int i=0;
    for(i=peopleSize; --i>=0;){
            IPeopleElement peopleElement = wdContext.nodePeople().createPeopleElement();
            peopleElement.setAge(i);
            peopleElement.setFirstName("John "+i);
            peopleElement.setLastName("Mills "+i);
            peopleElement.setOccupation("Consultant "+i);
            wdContext.nodePeople().addElement(peopleElement);
    }
    //@@end
}

 

The function fills the context node People that looks like this:

 

image

 

This node is mapped to the Interface Controller and to the View Controller. In the interface controller there is a function that references the fill method of the Component Controller:

 

public void fillPreanalyzePeople( ){
    //@@begin fillPreanalyzePeople()
    wdThis.wdGetPreanalyzeCompController().fillPeople();
    //@@end
}

 

Running the component on its own generates the following result:

 

image

 

To be able to use the “Source 1” component within other components we have to add it to the public part. You can do that as shown below:

 

image

 

You can build the component and we move to the next one – “Source 2“. First thing after we create the component is to import the “Source 1” as Used DC. Once we’ve done that, then we have to add the “Source 1” interface controller to the Used Web Dynpro Controllers of “Source 2”. After that our component should look something like this:

 

image

 

The node mapping is done between the interface controller of “Source 1” and the component controller of “Source 2”. One additional node is created that is called “calcPeople”. Then the context of the component controller has the following structure:

 

image

 

The “calcPeople” node is populated only with the number of entries in the other node using this function:

 

public void calculatePeople( ){
    //@@begin calculatePeople()
    int peopleCount = wdContext.nodePeople().size();
    wdContext.currentCalcPeopleElement().setTotal(peopleCount);
    wdContext.currentCalcPeopleElement().setTotalText("Total number of people:");
    //@@end
} 

 

The “calcPeople” node is then mapped to the “PerformVotingNewIView”, which has the following layout:

 

image

 

The other view is only used to combine the “Source 1” interface view and this one to create a complete representation. So after starting the “Source 2” component, the result is:

 

image

 

The result may not look as above, if you have forgotten to call the interface function that fills the “Source 1” nodes with data. After which you’ll have to call the calculate function and then the result should be the same as above. Before moving further let us map the “People” Node further from the component to the interface controller of “Source 2”. This way we give it simply to a component that would use “Source 2” later. Additionally we have to also add the component to the public part, so that it is available to be reused.

 

The third and last component is called “Consumer”, because it will consume both “Source 1” and “Source 2”. After the creation of the component, the first thing as before is to add “Source 2” to the Used DCs and then to the Used Web Dynpro Components. We won’t import “Source 1” since as we said in the beginning, we want to reduce the redundancy and keep our coding as optimal as possible. So how are we going to retrieve data from “Source 1” over “Source 2”? The solution follows…

 

The component structure of “Consumer” is represented on the next figure:

 

image

 

After the mapping the context of the component controller looks like this:

 

image

 

The additional node “OldestPersonNode” represents the name of the currently selected person in the table and is populated using a supply function (meaning it has its singleton property set to “true”) Since supply functions are not the topic of this blog let us skip this part for now and concentrate on the subject.

 

The layout of the “Source” view is shown below. We have two interface view containers and one item that is locally calculated (the current person). Whereas it is already clear where from the “Source 2” container comes from, it is not so for the “Source 1” view. We didn’t add it as Used DC, so we don’t have it in our Used Web Dynpro Components. This is also correct, because the solution is a bit tricky one.

 

image

 

To get access to our “Source 1” view, we would have to go one step back and open our “Source 2” component. There we should create a new window, in which to embed the “Source 1” view.

 

image

 

This way we make it available to the “Consumer”. Before we can see the new window available in the “Consumer”, we have to build the component “Source 2”.

 

Once all is done, the result of calling the “Consumer” component is:

 

image

 

Our task is achieved and the code is clean of additional calls and methods.

To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

  1. Raj Peddisetty
    During the migration process problems have been reported for this blog. The blog content may look corrupt due to not supported HTML code on this platform. Please adjust the blog content manually before moving it to an official community.
    (0) 

Leave a Reply