1 2 Previous Next

Open Source

25 Posts

Hi

 

SAP's software is known for its role running many of the world's largest companies, but not necessarily for its user-friendliness. As part of an ongoing effort to change this perception, SAP unveiled Fiori, a set of 25 lightweight "consumer-friendly" applications that can run on desktops, tablets and mobile devices, on Wednesday at the Sapphire conference in Orlando.

Fiori applications are written in HTML5, which makes multiplatform deployments possible. They also target some of the most common business processes a user might perform, such as creating sales orders or getting their travel expenses approved, according to SAP's announcement.SAP has grouped the initial Fiori applications into four separate employee types, including manager, sales representative, employee and purchasing agent. Fiori is priced per user and available now, but specific costs weren't disclosed Wednesday.It's possible to deploy Fiori as a single group of applications, as well as separate Web applications and within portals, according to a statement.Some 250 customers helped SAP develop Fiori and make the apps more user-friendly, SAP said.SAP has basically been compelled to develop something like Fiori, according to one observer."Customers want enterprise-class apps with consumer-grade experiences," said analyst Ray Wang, CEO of Constellation Research. "Fiori is one of the ways SAP customers can pull the data out of their existing systems, and democratize that information so that everyone can benefit from access to the SAP system.""For years, the issue was that SAP data was hidden or not easily accessed," Wang added. "This is one small step to make that change."SAP's App Haus, a startup-like development group within the company,has been working to create more usable and appealing application interfaces. It wasn't immediately clear Wednesday whether the App Haus team is involved with Fiori.

The vendor has also launched a product called Screen Personas, which gives users the ability to rejigger SAP software screens to better fit their job role and personal preferences.There's plenty more to come, SAP co-CEO Jim Hagemann Snabe said during a keynote.

 

Thank You

As some of you might know SAP is a contributor in the OpenSource project Eclipse. As part of that engagement we also organize so called "Eclipse DemoCamps" to show what one can do with this great development platform which is used a lot in the IT industry and is also the IDE of choice for SAP HANA Cloud Platform.

 

This year's Eclipse DemoCamp will be held at the day of planned release date for Kepler, the release name of Eclipse V4.3.

 

In case you are interested in joining the event you can register for free or even propose a speaking slot at the Eclipse DemoCamp and join speakers like Mike Milinkovich, the Executive Director of the Eclipse Foundation.

You'll be able to listen to interesting talks, get free drinks & food and a lot of possibilities to connect with other developers during the event.

 

So register today and join us in Walldorf for the Eclipse DemoCamp.

 

Best,

Rui

Welcome to the last episode about the SAP Open Source Summit 2012. In the first three episodes, I shared my overall impressions, key parts of my presentation on the corporate open source strategy, and insights from guest keynotes, respectively. Now I want to finish with a few areas that we are focusing on next.

 

Given that we now have an open source strategy in place at SAP, the focus is now much more on execution. Whenever you want to execute a strategy, you may however run into a number of challenges - be they of a technical, organizational or procedural nature. Specifically with regard to the much stronger use of open source and contribution to open souce projects, we have found four major types of challenges. These are reuse and versioning, alignment of release schedules, product security and long-term support as shown in the slide below. I used this slide also in my keynote last week at ApacheCon Europe 2012 to illustrate key challenges for managing open source from an enterprise perspective.

 

ApacheConEurope_Keynote_CvonRiegen.png

 

  • Reuse and Versioning
    If you focus on a given open source foundation like the Apache Software Foundation or the Eclipse Foundation, it is very likely that due to the nature of the foundation's development processes there is not much overlap between the various open source technologies. But open source projects today in many cases start somewhere else and don't necessarily follow a defined governance model. This is good since it is more flexible and allows the emergence of many different ideas. For example, GitHub today has almost 4.3 million projects. But the lack of coordination is also a challenge in that it becomes more difficult to find the right technologies and to understand their level of maturity and adoption. And it increases the likelihood of overlapping and similar technologies. This is not necessarily bad, but it can become a management challenge of open source adoption in the enterprise.

    One particular challenge in this regard is that different product teams might choose different technologies for the same purpose. The integration of, for example, four different open source XML parsers into our product line can result in maintenance overhead - four different technologies need to be maintained over the course of the products' support schedule. Another challenge is the selection of the right version of the open source technology. Even if all SAP product teams agree to select the same open source XML parser, they may have done so over the course of a few years and have chosen different versions of that XML parser. It is preferable to use only one version - and actually the most recent stable one - for all products because it also minimizes the risk to miss important security bug fixes in newer versions. But the upgrade might get complicated, for example, if the XML parser's APIs that were used to integrate it into the SAP product, have changed incompatibly.
  • Release Schedules
    The adoption of the most recent stable version of an open source technology is a reasonable goal to pursue on its own. But since the release schedules of the open source technology and the SAP product are not the same, this is not necessarily an easy task and some updates of the embedded open source technology might become necessary after the SAP product has already been shipped. There are some exceptions like the Eclipse Foundation that has decided to deliver one stable release of the Eclipse Platform once per year - this simplifies the planning exercise and allows us to, for example, develop a stable Eclipse release train SAP-internally on a yearly basis. The whole exercise can get more complicated when SAP is an active contributor to the open source project. By no means is there a guarantee that the extensions we developed SAP-internally will be adopted without any changes by the open source project lead and in time before the SAP product is being released to the market. This means that we sometimes need to live with a fork of the open source technology. The operational recommendation is to avoid such forks and to always seek a close alignment between the open source standard version and the version embedded in the SAP product.
  • Security
    Product security and security response management for SAP products clearly needs to include a responsibility for fixing security vulnerabilitites in embedded open source technologies. On the one side - since the source code of the open source technology is openly available and used by many other firms - there are more sources for finding potential security vulnerabilities. On the other side, this results in an obligation to even more quickly respond to such findings or adopt known resolutions. Enterprise customers need to be able to patch their systems with respecitve bug fixes before it is being discussed in the public. This may sound like a paradox since further development of the open source technology happens "in the open." But there are resolutions - the Apache Software Foundation, for example, has a process by which security vulnerabilities can be reported on a mailing list that is only accessible to the leads of the respective open source project. Until a resolution is available, the conversation continues in a private environment. The vulnerability is finally being reported publicly only at the time a bug fix has being made available. This significantly limits the risk that IT user organizations continue to run systems that are exploitable due to known vulnerabilities.
  • Long-Term Support
    SAP products are typically supported for at least seven years. Customers expect support for the complete solution, not just for the software components that were developed SAP-internally. From a support perspective, customers actually shouldn't need to know which open source technologies have been embedded. Consequently, we need to provide a means to support respective open source technologies, including the application of bug fixes as necessary. Fortunately, the various quality checks that are being applied when selecting open source technologies at SAP radically reduce the number of necessary bug fixes. But it can never be completely avoided and sometimes it is necessary for version 3.2 when the open source project has already released version 6.0 ...
    In principle, there are two main options: either to upgrade the embedded open source technology to version 6.0 or to apply a local bug fix to version 3.2. Both options can be rather complicated. An alternative is to join forces with other interested open source developers and users and to share the cost of maintaining older versions of the open source technology. SAP has long motivated such an approach for Eclipse projects. The recent establishment of the Long Term Support Industry Working Group (LTS IWG) is a good step in this direction and fortunately, a number of other Eclipse members do see the same need and have joined the LTS IWG to solve this important dilemma.

 

So I hope that this blog post series about the SAP Open Source Summit 2012 has been useful for you. From my perspective is was good to see a strong focus on operational excellence, knowledge sharing and applying open source development principles SAP-internally. Let me conclude with Mike Milinkovich's words: "Open source software is really really mainstream." And the journey will continue.

 

Here is the overview of the blog post series again:

  1. Overall Impressions
  2. What we think - SAP Open Source Strategy
  3. Insights from keynotes
  4. What we do next (this post)

In this blog post we'll look at how one can use Spring Security framework together with the usual way of securing a JEE application on NetWeaver 7.3 and what this can bring us. Here are the useful links :

 

 

For the reference, I've tested this setup with Spring Security 3.1.3.RELEASE (which in turn depends on Spring MVC 3.0.7.RELEASE).

 

Spring Security is a popular and very flexible framework which allows to configure and manage all aspects of securing a web application : authentication, authorization, access control to domain objects. One of the many useful things which this framework provides is a spring-security-taglibs module which allows one to protect the various pieces of the JSP page using security tags tied to the user's role membership (authorization). For example, we can have a JSP like this :

 

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>

<p>Hello, this page is accessible to all users with ROLE_EVERYONE</p>

<sec:authorize access="hasRole('ROLE_SFLIGHT_USER')">
    <p>This text and link below should only be visible to users with
    ROLE_SFLIGHT_USER</p>
    <a href="<%=request.getContextPath() %>/secure">secure page</a>
</sec:authorize>

 

Notice the use of sec:authorize tag which protects access to the part of the page depending on whether or not the current user has a role SFLIGHT_USER. We'll discuss below how we can configure Spring Security to work seamlessly with the security services provided by out JEE container. The idea behind this integration is quite simple: NetWeaver already handles the user authentication for us, there is also a mechanism to map the UME roles of the portal user to the roles referenced in the web.xml of our application. All we have to do is to find a way to make Spring Security framework recognize these roles as the "granted authorities" associated with the authenticated user.

 

We start with a simple web application set up. Here are the interesting parts of our starting web.xml :

 

<login-config>
    <auth-method>TICKET</auth-method>
</login-config>

<security-role>
    <role-name>EVERYONE</role-name>
</security-role>

<security-role>
    <role-name>SFLIGHT_USER</role-name>
</security-role>

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Spring Security Integration Test Application</web-resource-name>
        <url-pattern>*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>EVERYONE</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
</security-constraint>

 

We chose a "tiket" authentication method for our web application meaning that the user will be considered authenticated if he or she previously logged in on the portal and that there is JSESSIONID and MYSAPSSO2 cookies are present in his or her browser session (usual SAP SSO via SAP Log on ticket). We declare two security roles "EVERYONE" and "SFLIGHT_USER" for our example. The first one is a general role assigned to every UME user. The other one is an example role which we can create and assign to some test user. We then protect any access to our web application by setting url-pattern of the security constrain to "*". The idea is that we let the JEE container to manage the authentication of the user but the finer granularity access protection within the application we will delegate to Spring Security. For the mapping between the UME roles and the web application security roles we also need this in the web-j2ee-engine.xml file of the web application module :

 

<security-role-map>
    <role-name>EVERYONE</role-name>
    <server-role-name>EVERYONE</server-role-name>
</security-role-map>

<security-role-map>
    <role-name>SFLIGHT_USER</role-name>
    <server-role-name>SFLIGHT_USER</server-role-name>
</security-role-map>

 

Now we need to set up and configure the filter chain used by Spring Security. This is done by specifying a Spring's application context file containing all the security configuration in our web.xml file :

 

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/context/security-config.xml</param-value>
</context-param>
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

 

The security configuration file, security-config.xml, uses Spring Security namespace for convenience. It uses the security scenario of "pre-authentication" and relies on two classes provided for us by the framework: J2eePreAuthenticatedProcessingFilter and  which integrates with the container authentication process by extracting user principle from the HttpServletRequest and J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource which is responsible to map a configured set of the security roles specified in the web application descriptor file to the set of GrantedAuthorities provided the user membership in these roles has been established. Here is the security-config.xml file :

 

<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">

    <http auto-config="true" use-expressions="true">
        <jee mappable-roles="EVERYONE,SFLIGHT_USER" />
        <intercept-url pattern="/**" access="hasRole('ROLE_EVERYONE')" />
        <intercept-url pattern="/secure/**" access="hasRole('ROLE_EVERYONE')" />
    </http>

    <authentication-manager>
        <authentication-provider ref="preAuthAuthenticationProvider"></authentication-provider>
    </authentication-manager>

    <beans:bean id="preAuthAuthenticationProvider"
        class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
        <beans:property name="preAuthenticatedUserDetailsService">
            <beans:bean
                class="org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService"></beans:bean>
        </beans:property>
    </beans:bean>
</beans:beans>

 

Notice the use of "jee" element in the "http" configuration, it is a shortcut for configuring an instance of J2eePreAuthenticatedProcessingFilter filter and registering it with the defaulf filter chain. Also, by default all the JEE security roles specified in the "mappable-roles" attribute will be mapped to the GrantedAuthorities with the names prefixed by "ROLE_".

 

Once the pre-authentication mechanism is successfully configured we can protect URL access using expressions of the kind "hasRole('ROLE_FROM_UME_HERE')" in the global "http" configuration element and in the security tags in our JSPs. For the reference, this is the Spring MVC configuration file, mvc-config.xml, which I've used for the the web application, it uses "mvc" namespaces for convenience :

 

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <mvc:annotation-driven />

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <mvc:view-controller path="/" view-name="index"/>
    <mvc:view-controller path="/secure" view-name="secure"/>
</beans>

 

It could be referenced in the web.xml file in the standard way :

 

<servlet>
    <servlet-name>springMvcServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/context/mvc-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>springMvcServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

 

Using Spring Security in the standard JEE web application can be very useful. Other than the use of the security tags in the JSPs, described in this post, one can think of securing method's access in Java beans or using Access Control Lists (ACL) management for example.

In the first two episodes of this blog post series about the SAP Open Source Summit 2012, I shared my overall impressions and key parts of my own presentation on the corporate open source strategy, respectively. Now I want to touch upon insights from the keynotes that our guest speakers delivered.

 

Mike Milinkovich, Executive Director, Eclipse Foundation, presented on Foundations 2.0. He offered his slides to be posted on SCN, see here. As already mentioned in my first blog post in this series, Mike stressed the point that it is commonly unknown that SAP is a strong contributor to the Eclipse Foundation. The Eclipse ecosystem is still growing - today, there are more than 2 mio downloads per month. Also, Eclipse is known for its predictabie, yearly releases and the level of corporate engagement, which was one of the differentiators when the foundation was created more than 10 years ago.

Recognizing a few trends in the software industry such as "software is everywhere" and "open source is really really mainstream", he characterized the next generation of open source foundations, which is also where Eclipse is going:

  1. Technology-agnostic Eclipse is already much more than an IDE only and applies to practically all programming languages (including ABAP ...). The foundation will continue to serve additional purposes and welcome other technologies that can make use of the development and IP management principles that it is known for.
  2. Git-based The adoption of Git as a version control and source code management system for distributed development is still growing and Eclipse has decided to migrate to a Git-based common build infrastructure, which will presumably simplify the daily life of Eclipse committers.
  3. Long-term support Particularly in enterprise environments, the requirement of long-term support (or sometimes long long-term support ...) is obvious and the establishment of the Long Term Support Industry Working Group supports the development of respective development and support models.
  4. User-led More and more end-user organizations from different industries observe the opportunities (or sometimes the need) to increase the level of collaboration, including the joint work on software projects. Eclipse already has a number of industry working groups such as Polarsys for embedded systems or LocationTech for location-aware software and Mike believes that the trend of more end-use involvement will continue.

 

Andrew Aitken is SVP, Olliance Group, a Black Duck company and an open source consulting firm. He has consulted numerous software companies on how to embed open source development and licensing approaches in their corporate strategy. From his point of view, open source is already in its fourth generation. In the beginning, it was a rather extreme movement with rather extreme characters like Richard Stallman and Bruce Perens. Then, open source emerged and became a means for commercial success: Red Hat, MySQL and SpringSource are examples of commercially quite successful companies with an open source based business model. Thirdly, the more traditional vendors complement their business model with open source approaches - today, there is hardly any software vendor that does not have a defined approach towards open source. And the fourth generation is - in line with what Mike observes - the involvement of end-users. NYSE, Airbus, BMW and NASA, for example, are all quite actively engaged in open source projects that are specific to their industry vertical.

 

Dirk Riehle, Professor for Open Source Software at the University of Erlangen-Nürnberg, presented on one of his favorite topics: Inner Source. Inner Source is what he calls "open source best practices applied to firm-internal software development." He and his team have interviewed and worked with a number of corporations, both software vendors and end-user organizations to see if the expected benefits of inner source (better code reuse, more knowledge sharing, improved resource allocation and higher job satisfaction) actually apply. While he in general confirms this, he distinguishes between two forms of inner source - volunteer (i.e., self-managed) and managed. Managed inner source requires a "defined and actively managed governance process." The right choice of model depends on the types of challenges an organization or a project is facing, which varies between developer skills, developer mindset and management mindset. More research from Dirk can be found on his blog.

 

Last but not least, Jono Bacon presented on Communities and what makes them strong and vibrant. For him, sense of belonging and sense of purpose are the most important characteristics the individual community members should feel to make the community a coherent one. Communities are obviously not restricted to software development (and of course not to open source software), but many principles of successful communities can also be seen in software-related communities. For example, the importance of providing kudos to active members, particularly new ones that start contributing, can not be overestimated. A simple "thank you" for committing a patch that resolves an annoying bug is key to keep the contributor's sense of belonging and the overall community more active. Jono has written a well-known book "The Art of Community" published at O'Reilly and continues the dialogue on the Art Of Community Online.

 

Next time, I'll finish this series and write about what SAP is - presumably - going to do next in the context of open source software.

 

In terms of the SAP Open Source Summit 2012 blog series, here is the overview again:

  1. Overall Impressions
  2. What we think - SAP Open Source Strategy
  3. Insights from keynotes (this post)
  4. What we do next

In this blog I'll share with you an alternative to the SAPUI5 development on the NetWeaver platform. SAPUI5 is an interesting and innovative effort from SAP on the front of modern UI development. But at the time of writing this post, it is still in an evaluation beta stage and it seems like there is still no decision about the licensing scheme that SAP will adopt for this technology. Since NetWeaver has been able to take advantage of Java 5 and JEE 5 and especially since it has become very easy to deploy a third-party JARs with a webapp deployed on this platform, we have a multitude of free and open source alternatives available for developing modern UI in the same way SAPUI5 has been designed. I will describe a way of using a very cool JavaScript framework, Dojo, together with my favorite MVC framework, Spring, to build a simple hello world webapp which demonstrates how these technologies can be used together on NetWeaver 7.3.

 

The sources for this webapp can be found in the Code Exchange project dojoui.

 

Note: I assume that you are already at least somewhat familiar with Spring MVC and Dojo frameworks.

 

Download a Dojo distribution from their site. I used the latest release, 1.8.1. You'll need to create a JAR containing these packages under the path /META-INF/resources/. The idea is that we will delegate to Spring the care of serving and caching these JavaScript files from this JAR for us, instead of bundling them as is in our WAR.

 

You also need to get all the JARs necessary for Spring MVC setup. There many ways to do this. I use Apache Ivy for this purpose. You can create a simple Java project in NWDS, import the single build.xml file from the Ivy's site and create a simple target which will retrieve Spring's libraries and their dependencies for us from the Maven repository. Here is the target:

 

<target name="resolve-and-retrieve" depends="install-ivy" description="--> resolves dependencies decalred in ivy.xml file">
    <ivy:resolve file="${basedir}/ivy.xml" transitive="true"/>
    <ivy:retrieve/>
</target>

 

It will resolve the dependencies declared in ivy.xml file, download them and put then in lib folder. Here are the contents of ivy.xml file:

 

<info organisation="your.org" module="anything" />
<configurations defaultconfmapping="default->default"></configurations>
<dependencies>
    <dependency org="org.springframework" name="spring-webmvc" rev="3.1.0.RELEASE" />
    <dependency org="cglib" name="cglib" rev="2.2" />
    <dependency org="org.codehaus.jackson" name="jackson-mapper-asl" rev="1.9.10" />
</dependencies>

 

You might need ivysettings.xml file, as well, here it is:

 

<ivysettings>
    <settings defaultResolver="chain" />
    <resolvers>
        <chain name="chain">
            <ibiblio name="central" m2compatible="true"></ibiblio>
            <!-- uncomment if you want to use Spring's milestone libraries -->
            <!-- 
            <ibiblio name="spring-milestone" m2compatible="true"
                root="http://repo.springsource.org/milestone"></ibiblio>
            -->
        </chain>
    </resolvers>
</ivysettings>

 

After retrieving the libraries you should have all the JARs (together with the dojo-1.8.1.jar created above) needed to create a simple webapp. You can see all the JARs needed in the image of the webapp structure at the end of this post.

 

Create a simple webapp project in NWDS (tmp~dojo~web) and assign it to an EAR (tmp~dojo~ear). Copy all the JARs into /WEB-INF/lib directory of your web project, they will be deployed to the server. Now we need to set up Spring's MVC for our webapp. This requires registering Spring's Dispatcher servlet in our web.xml file. Here it is:

 

<servlet>
    <servlet-name>SpringMvcDispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>ch.unil.dojo.web.config.WebConfig</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>SpringMvcDispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

 

Spring MVC can be configured using Java annotations, this is how I have done it:

 

/**
 * Web context configuration to be processed by {@code
 * AnnotationConfigWebApplicationContext} and specified as {@code
 * contextConfigLocation} parameter for {@code DispatcherServlet}, see {@code
 * web.xml} file.
 * <p>
 * {@code EnableWebMvc} annotation configures default MVC infrastructure
 * including an instance of {@code MappingJacksonHttpMessageConverter} Json to
 * Java converter for request handlers. {@code ComponentScan} annotation
 * specifies the base package which will be scanned for the {@code Controller}
 * annotated classes.
 * 
 * @see org.springframework.web.servlet.DispatcherServlet
 * @see org.springframework.web.context.support.AnnotationConfigWebApplicationContext
 * @see org.springframework.web.servlet.config.annotation.EnableWebMvc
 * @see org.springframework.http.converter.json.MappingJacksonHttpMessageConverter
 */
@EnableWebMvc
@Configuration
@ComponentScan(basePackages = "ch.unil.dojo.web")
public class WebConfig extends WebMvcConfigurerAdapter {

    // set up the default view resolver, mapping logical view name
    // to a JSP with the same file name
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/pages/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

    // add handlers for the static resources (js, css, images),
    // will look up and cache Dojo files from the jar on the classpath
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/META-INF/resources/")
            .setCachePeriod(31556926);
    }

    // set up the redirection to the main view if the root URL is accessed
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
    }
}

 

Notice how we are setting up a special ResourceHandler for all the Dojo JavaScript files which will be served from the JAR on the classpath and even cached for faster subsequent accesses.

 

Now we can create our JavaScript font-end UI using Dojo. Create a JSP page called index.jsp in /WEB-INF/pages/ folder. The Spring will automatically use this view for all requests to the root of the web application. Here are the contents of this file:

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Testing Dojo</title>
<link rel="stylesheet" type="text/css"
    href="<%=request.getContextPath()%>/resources/dijit/themes/claro/claro.css">
<script src="<%=request.getContextPath()%>/resources/dojo/dojo.js"
    data-dojo-config="async: true,
    packages: [{name: 'js', location: '<%=request.getContextPath()%>/resources/js'}],
    gfxRenderer: 'svg'"></script>
</head>

<body class="claro">

    <script type="dojo/require">at: "dojox/mvc/at"</script>
    <div data-dojo-type="dojox/mvc/Group" data-dojo-props="target: model">
        <div data-dojo-type="dijit/form/TextBox"
            data-dojo-props="value: at('rel:', 'name'), placeHolder: 'First Name',
                properCase: true, trim: true"></div>
        <div id="submitBtn" data-dojo-type="dijit/form/Button"
            data-dojo-props="label: 'Submit'"></div>
        <div id="surfaceDiv"></div>
    </div>

    <script>
    require(["js/utils", "dojo/_base/kernel", "dojo/when", "dojo/parser", "dojo/json", "dojo/Stateful", 
             "dojo/on", "dojo/mouse", "dijit/registry", "dojox/gfx", "dojox/gfx/fx", "dojo/colors"],
            function(utils, kernel, when, parser, json, Stateful,
                    on, mouse, registry, gfx, gfxAnim, Color){

        //create a model
        var model = kernel.global.model = new Stateful();

        //parce the document, then connect the submit button
        when(parser.parse(), function() {
            //create SVG surface
            var surface = gfx.createSurface("surfaceDiv", 400, 100);
            registry.byId("submitBtn").on("click", function(evt){
                //make Ajax request
                when(utils.ajaxRequest("<%=request.getContextPath()%>/greet",
                        json.stringify(model)), function(data) {
                     //clear previous shape
                    surface.clear();
                    //crete text shape
                    var text = surface
                        .createText({x: 200, y: 50, text: data.greeting, align: "middle"})
                        .setFont({family: "Arial", size: "20pt", weight: "bold"})
                        .setFill(Color.named.skyblue);
                     new gfxAnim.animateTransform({
                         duration: 1500,
                         shape: text,
                         transform: [{
                             name: "rotategAt",
                             start: [0, 200, 50],
                             end: [360, 200, 50]
                         }]
                     }).play();
                });
            });
        });
    });
    </script>
</body>
</html>

 

This is a simple hello world webapp but with a little Dojo twist. It collects the user's name and sends to the Spring's controller in a form of an Ajax request with the name serialized as a Json string. On the cotroller's side the Json string from the body of the request is automatically converted to a POJO of the corresponding structure by the MappingJacksonHttpMessageConverter instance registered with Spring MVC by default (it's a part of EnableWebMvc configuration). Once the greeting message is generated it is stored as a value of the POJO's property and the POJO is serialized to the body of the HTTP response in the form of a Json string again automatically by the Jackson mapper. The returned Json response is parsed by Dojo which displays the greeting message as a rotating SVG text shape.

 

As you can see, we don't actually use a lot of JSP's functionality, it is mostly a plain HTML page with some JavaScript. However, we need a reference to the context path of the webapp which we can obtain by using a scriplet <%=request.getContextPath()%>. We also use a custom module, "js/utils", which Dojo is instructed to look up under /resources/js location. I have put this file on the classpath (src folder) under /WEB-INF/resources/js/utils.js this way the Spring's ResourceHandler servlet can pick it up as well. Actually, this is the only way that I found to reference my custom module on NetWeaver if I wanted to have it served by the Spring's resources servlet. Here are the contents of this file, it's just a simple utility to generate an asynchronous Ajax request to the server using Dojo's handy "dojo/request" module.

 

define(["dojo/request", "dojo/Deferred"], function(request, Deferred){
    return {
        ajaxRequest: function(path, data, sync){
             var def = new Deferred();
            request.post(path, {
                headers: {"Content-Type": "application/json"},
                data: data,
                handleAs: "json",
                sync: (sync || false)
            }).then(function(data){
                def.resolve(data);
            },
            function(error){
                def.reject(error);
            });
            return def;
        }
    };
});

 

The controller class which is responsible for handling the Ajax request is given below:

 

/**
 * Controller which will handle all incoming HTTP requests. Registered in the
 * MVC infrastructure via {@code ComponentScan} annotation used in the web
 * context configuration class.
 */
@Controller
public class AjaxController {
    private static final Logger logger = Logger.getLogger(AjaxController.class);

    /**
     * Request handling method applicable to any POST request with a header
     * {@code Content-type: application/json} and the path {@code /greet}.
     * Spring automatically converts the Json string from the body of the
     * request via {@code MappingJacksonHttpMessageConverter} to an instance of
     * {@code Greeting} form and serializes it back to a Json string set to the
     * body of the response.
     * 
     * @param form person data
     * @return greeting data
     * 
     * @see org.springframework.http.converter.json.MappingJacksonHttpMessageConverter
     */
    @RequestMapping(value = "/greet", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
    public @ResponseBody
    Greeting greet(@RequestBody Greeting form) {
        logger.debug("Processing Ajax request for /greet with form: " + form);
        form.setGreeting("Hello, " + form.getName() + "!");
        return form;
    } 
}

 

As you can see Spring makes it very easy for us to work with this kind of requests and thus it is a particularly good choice for the server-side Ajax processing.

 

Here is an outlay of the entire webapp project in NWDS for reference:

 

 

We can recap the things that we have used in this showcase and the advantages of this architecture.

 

1) Dojo front-end

 

Dojo is an excellent JavaScript framework, it is reach and constantly growing, uses AMD module loading, has a vibrant community and it is open source. The learning curve for Dojo is probably not much steeper than the one for learning SAPUI5 considering that you would have to learn JQuery with SAPUI5 at some point. The advantage of using Dojo is that you don't need to use the NetWeaver at all. I actually developed the entire webapp in STS with a Tomcat 6. Of course you will not get the code assist for the JavaScript files as you have with SAPUI5 plugin but at least it is free.

 

2) Spring MVC

 

Spring MVC framework allows to configure a clean separation of concern, RESTfull architecture for a webapp very easily, especially when it comes to conversion to and from Json requests. It all happens behind the scenes with Jackson mapper allowing one to implement server-side logic with simple POJOs. If you like this setup you can easily imagine using Sprin's Security to make your webapp secure or to use Spring CCI with an EJB session facade to connect to an ABAP backend.

In the first episode, I shared my overall impressions from the SAP Open Source Summit 2012. Now I want to share key parts of my own presentation, which mostly focused on the corporate open source strategy, its reasoning and how we operationalize it.

 

First of all, there is no room for a stand-alone open source strategy. To make sense, it clearly needs to support the overall product strategy. Secondly, it needs to allow us to gain something, for example, to increase development productivity or create more value-added features. Otherwise, we could all live a not invented here syndrome and develop all our products in a completely proprietary manner. And thirdly, it needs to executable without compromising our product standards and quality goals.

 

Let's now explore the strategy itself. It centers around three dimensions: usage of open source in SAP products, contribution to open source projects, and interoperability with open source technologies. The picture below says it all.

 

OSS_Strategy.png

 

That's it. Pretty straight-forward. Essentially, it describes what we are doing for quite some time in some areas already. No big surprise. But now it is written down, explains the business benefits and we can focus on its execution. Of course, there are a number of questions. What does "proven, broadly adopted" mean? When exactly should we contribute to open source projects and which parts of our products? And which interoperability scenarios are important from our customers' perspective?

 

O.k., let's focus on the execution and see how we can answer the operational questions. Here are four strategic recommendations providing more guidance on how to execute the strategy.

 

Recommendation1.png

 

Looking a few years back - when open source at SAP was managed as an exception - I can say that this is pretty much a 180° turn of guidance. Of course, there can be many reasons why an open source product is not the right choice. It may not be a good functional fit or expensive to make it fit. There might be doubts about the future of the project. The open source license may not be compatible with the intended use case. But if such key questions can be answered positively, the use of open source is the better economic decision for the reasons mentioned above.

 

Here is recommendation #2.

 

Recommendation2.png

 

In the majority of cases, the open source software embedded in SAP product doesn't need any modifications. This is due to the fact that we always analyse the maturity of the software and determine the adoption rate in the industry. But sometimes, there is a need to fix a bug and modify or enhance the software. In those cases, it would be a mistake to keep these changes proprietary. This is where Mike Milinkovich would say "keeping it proprietary is not an asset - it is a liability." It is econmically the better choince to contribute the changes back to the open source project so that they can be included in the next version of the original open source software. This significantly reduces the cost of reintegrating the newest version of the open source software. And it - through our active participation - protects the future of the open source project and helps avoiding the "tragedy of the FOSS commons" as identified by Schweik and English in that open source software can only be successful if there is continued contribution from diverse sources.

 

This covers contributions to existing open source projects. But what are the factors to determine when to start a new open source project? This is what recommendation #3 is all about.

 

Recommendation3.png

 

Like in recommendation #1, this is a major turn in our approach to open source (compared to a few years back). When in the past, every single line of proprietary code was considered to be intellectual property that by all means needed to be kept proprietary, we now do a much more comprehensive cost-benefit analysis and include benefits such as protection of investments through standardization and utilization of external contributions. Software components that are not SAP-specific and non-differentiating can actually benefit a lot from being made available as open source - we can simply avoid to compete with our proprietary approach in cases where competition increases cost (instead of increasing revenues). The level playing field created by providing the software as open source invites others to join us in making the software more relevant in the future. The Eclipse Memory Analyzer was the first official open source project created by SAP under this new approach (of course, SAP DB / SAP MaxDB was open source for many years before) and allowed us - in this case - to join forces with IBM and others to make it work on other Java Virtual Machines, for example.

 

Taking contributions to existing projects and creation of new projects together, SAP developers contribute to more than 50 open source projects. A selection of contributions is listed at this SCN page.

 

Finally, recommendation #4 covers interoperability between SAP and open source technologies.

 

Recommendation4.png

 

In many cases, SAP customers already use open source technologies in their system landscape and may even have built up skills on how to use, administrate or develop with the open source technology. Considering those cases, it makes a lot of sense to illustrate our customers on how to use such open source technologies in combination with SAP technologies to eventually reach a more complete solution portfolio and protect our customers' investments in the open source technologies. Consequently, we work in various areas to reach a higher level of interoperability between SAP and open source technologies, partly combined with contributions to the respective open source projects. Even in the case of SAP HANA (see picture above), a number of open source technologies - like the statistical computing library R or the distributed and "big data" computing technology Hadoop complement our offering.

 

I believe this is enough food for thought for today and look forward to your feedback.

 

In terms of the SAP Open Source Summit 2012 blog series, here is the plan again:

  1. Overall Impressions
  2. What we think - SAP Open Source Strategy (this post)
  3. Insights from keynotes
  4. What we do next

As Matthias Steiner already mentioned in his blog post SAP NetWeaver Cloud & Open Source - A match made in heaven on Monday, we organized the third SAP Open Source Summit last week Thursday and Friday. While this was an internal event, the topic obviously is not. We also had five external keynote speakers -  it was great to get their perspective and to use the opportunity for more in-depth discussions on trends and future opportunities. More on that the next episodes.

 

A theme that I heard more than once from our guests is that they recognize from the summit sessions and discussions (as well as from earlier interactions) that SAP is a quite active open source consumer and contributor, but only very few people outside of SAP know about that. It seems to be one of the best kept secrets - even though there is no reason to keep it secret. Point taken. This post is an(other) attempt to change that.

 

Let me start with an example. One that Mike Milinkovich mentioned during his keynote about Foundations 2.0: SAP is the third-largest committer to Eclipse projects. As of today, 31 committers from SAP have done 63,867 commits to 26 Eclipse projects with together 3,127,480 lines of code. I don't think that we are or need to be in a race here to compete for the second or third place. I think that the numbers just say that open source contributions are a normal course of action for SAP and become increasingly important from a product development perspective.

 

The other example I saw last week is the discussion around best practices for open source contributions. At the past open source summits (2009 and 2010, those days organized by Erwin Tenhumberg) we talked a lot about how to become a committer at an open source project. This time, we had a number of committers and even project leads on stage sharing their experience and recommendations. It is interesting to notice that Stephan Klevenz (committer to odata4j at Google Code), Matthias Sohn (co-lead for EGit and JGit at Eclipse), Krum Tsvetkov (co-lead for Eclipse Memory Analyzer, originally initiated by SAP), and Florian Mueller (chair and VP for Apache Chemistry) all work for SAP. And now the discussion was much more about effective project management, IP management done by open source foundations or procedural questions like how to report and handle security vulnerabilities in open source code (a topic that is better not discussed in the public until a fix is available).

 

Now, instead of overloading this blog post, my plan is to write a series on the Open Source Summit 2012 as follows:

  1. Overall Impressions (this post)
  2. What we think - SAP Open Source Strategy
  3. Insights from keynotes
  4. What we do next

 

I hope this will be interesting for a broader audience and look forward to your feedback.

On June 20, 2012, we have celebrated the Eclipse Juno release at our fourth Eclipse DemoCamo in Walldorf. Again a big crowd showed up. They saw cool demos, covering various areas like UI technologies and testing, modeling, SAP variant configuration, and support for Cloud development via Git and Gerrit. Many thanks to all presenters!

 

Like always, everyone recovered from this serious business during the Happy Hour: barbecue, tons of networking opportunities, and the sound of "East Ring Company" made it easy to relax.

 

We have linked some pictures from the DemoCamp Wiki page.

 

We're looking forward to seeing even more people at the Kepler DemoCamp next year!

When the SAP Java Virtual Machine team decided to join the OpenJDK project last year, they first of all wanted to understand the overall direction and governance structure of the project. After Volker Simonis and other team members contributed a few bug fixes and minor enhancements, they quickly observed that their contributions were not only welcomed, but that there are many similar interests among the different OpenJDK project members - the most important one being to protect the future of Java. What a bold statement ... in practice this means that through active participation and contribution from a broader group of participants, the work can be shared and innovation for the Java platform can jointly be defined by means of one standard implementation. An interesting observation is obviously that the participants include key vendors such as Oracle, Red Hat, Apple, IBM, and SAP that in various regards are competitors in the marketplace. But there is less and less reason to compete on Java Virtual Machine and Java Development Kit features where the same requirements are implemented differently.

 

Based on this experience, SAP today decided to significantly incresae its contributions. Please read Volker Simonis' blog post on the OpenJDK mailing list about a new project proposal. We now plan to contribute whole platform ports in a belief that it is economically better to standardize our own implementation than to keep it proprietary. The first platform port that we are going to contribute is Linux on PowerPC. Based on that, we will work together with IBM and others and also use it as a basis for the AIX on PowerPC port. Depending on the outcome, other ports for other platforms might follow. This will also help us to better integrate and align our own platform ports and extensions with current Java developments, and it will let the OpenJDK community profit from SAP’s longstanding experience in Java and Java VM technology. Every OpenJDK user will be able to benefit from a broader choice of platforms, an important consideration for many SAP customers. SAP’s commitment to deliver a high class, commercially licensed Java Virtual Machine remains unchanged. SAP is currently delivering its commercial Java based products with SAP JVM, a certified Java Virtual Machine (JVM) and Java Development Kit (JDK), compliant to the Java Standard Editions 1.4, 5, 6 & 7 on all 14 platforms supported by SAP.

In this series (part 1, part 2) we have looked at the way we can combine some leading Java technologies to create a multi-tier application with JSF 2.0 front-end, EJB session facade and layer for communicating with the ABAP back-end via JRA adapter. All of the layers take advantage of Spring framework which provides such utilities as Common Client Interface (CCI) abstraction for working with the JCA connection factory of the AS, and the jee:jndi-lookup mechanism for looking up resources and EJBs in the JNDI context. Below are some of the screenshots for the proof-of-concept application built using the techniques described in this series of posts. It uses Primefaces with cupertino and redmond themes (with the font set to match the one from SAP look-and-feel).

 

Note: the source code is available on Code Exchange project jsf20-nw73-showcase.

 

 

 

 

 

In the part 1 of the series we have set up an EJB session facade with the Spring's CCI utility code for communicating with the ABAP back-end via JRA adapter deployed and configured on the AS. In this post we will look at the way we can deploy the web front-end of the application based on JSF 2.0 reference implementation. In addition, we will try to use a popular UI components library for JSF, Primefaces.

 

The reason for this (unusual) combination of technologies, is that NW 7.3 supports only JSF 1.2 out of the box, with a custom UI components library for the SAP look-and-feel. However, the JSF technology has greatly progressed since the JSF 1.2 edition, and the multitude very useful UI components libraries have been created for developing the UI with this technology. Here are some of them: Tomahawk, Richfaces, Primefaces, IceFaces, just to name a few. For our proof-of-concept I have chosen a popular combination of Mojarra JSF 2.0 implementation combined with Primefaces library.

 

Now available part 3 of the series. Source code is available on Code Exchange project jsf20-nw73-showcase.

 

Deploying Mojarra to the AS

 

First we need to substitute the JSF 1.2 library used by default by the AS with the Mojarra 2.1.7 implementation of JSF 2.0. I'm reproducing below the steps described by Schindler Ingo in the forum post: JSF2 on Netweaver 7.3 (see the correct answer, and the remark at the end of the thread about "gzip-compression of the AS"), whose insight proved invaluable in this task.

 

Another very interesting article by Goran Stoiljkovski explains well how the AS resolves classpath dependencies and what is needed to deploy an application using so called heavy resource loaders. After several attempts, I settled on the Ingo's proposed method of deploying and referencing Mojarra as a library on the AS.

 

Download Mojarra library JAR. I chose javax.faces-2.1.7.jar, the latest at the time of the writing of this post. Create a simple General --> Project project in the NWDS workspace. Add the following files and folders to the project (Ingo's suggestion):

 

 

What we are doing here is creating by hand  the contents of the SDA file (mojarra217.sda) which will contain our JSF 2.0 library in order to deploy it to the AS. Later our application's EAR will reference this (deployed) library in it's application-j2ee-engine.xml descriptor. The easiest way to go about creating such SDA is to locate any library SDA already deployed on the AS, copy it locally, change the extension to .zip and unzip it. Then all the one needs to do is to adjust slightly the contents of the relevant files. Another way is to create the library SDA using the batch script make_SDA.csh found in <path_to_java_instance>/j2ee/deployment/scripts directory on the server. Look at ReadMe.txt for usage guidelines, and library.properties or primary-library.properties templates in the same directory.

 

Here are the contents of the SDA's files shown above:

 

application-j2ee-engine.xml

 

<application-j2ee-engine xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="application-j2ee-engine.xsd">
<provider-name>local.j2ee</provider-name>
</application-j2ee-engine>

 

Provider name is arbitrary, but you should be consistent throughout the SDA.

 

MANIFEST.MF

 

Manifest-Version: 1.0
Implementation-Title: javax~faces~2.1.7
Implementation-Version: 1
Implementation-Vendor-Id: local.j2ee
Specification-Vendor: SAP AG

 

Notice the Implementation-Title and Implementation-Vendor-Id entries.

 

SAP_MANIFEST.MF

 

Manifest-Version: 1.0
Ext-SDM-SDA-Comp-Version: 1
softwaretype: library
JarSAP-Standalone-Version: 20090803.1000
JarSAPProcessing-Version: 20090907.1000
deployfile: sda.xml
archivetype: DC
keyname: javax~faces~2.1.7
keyvendor: local.j2ee
keylocation: Deployment Manager
keycounter: 1
componentelement: <componentelement  name="javax~faces~2.1.7" vendor="local.j2ee" componenttype="DC" subsystem="NO_SUBSYS" location="Deployment Manager" counter="1" deltaversion="F" updateversion="LB-20120413181800" componentprovider="Deployment Manager" archivetype="DC"/> 
JarSL-Version: 20100616.1800
compress: true

 

Notice the softwaretype, keyname entries and the name and vendor attributes in the componentelement.

 

sda-dd.xml

 

<SDA>
<SoftwareType>J2EE</SoftwareType>
<engine-deployment-descriptor version="2.0">
    <substitution-variable>
      <variable-name>com.sap.dc_name</variable-name>
    </substitution-variable>
    <substitution-variable>
      <variable-name>com.sap.dc_vendor</variable-name>
    </substitution-variable>
    <substitution-variable>
      <variable-name>com.sap.sld.GatewayHost</variable-name>
    </substitution-variable>
    <substitution-variable>
      <variable-name>com.sap.sld.GatewayService</variable-name>
    </substitution-variable>
</engine-deployment-descriptor>
</SDA>

 

sda.xml

 

<SDA>
    <SoftwareType>library</SoftwareType>
    <engine-deployment-descriptor version="2.0" />
</SDA>

 

Standard content for SDA deployment descriptor.

 

provider.xml

 

<!DOCTYPE provider-descriptor SYSTEM "library.provider.dtd">
<provider-descriptor>
    <display-name>javax~faces~2.1.7</display-name>
    <component-name>javax~faces~2.1.7</component-name>
    <major-version>2</major-version>
    <minor-version>1</minor-version>
    <micro-version>7</micro-version>
    <provider-name>local.j2ee</provider-name>
    <references>
        <reference type="library" strength="weak" provider-name="sap.com">servlet</reference>
    </references>
    <jars>
        <jar-name>lib/javax.faces-2.1.7.jar</jar-name>
    </jars>
</provider-descriptor>

 

Hint: one can find DTD files useful when creating some of these XML files by hand in <path_to_java_instance>/j2ee/cluster/server0/dtd directory on the AS.

Zip the project root directory and rename the resulting file with .sda extension (mojarra217.sda). You can now deploy the resulting SDA to the AS using Deploy View, External Deployable Archives.

 

 

Using the steps from Goran's article we can now check if the library was successfully deployed on the AS. Use SAP Management Console of NWDS to find out which is the port for the telnet on your AS, by looking at the Access Points, usually it is 50008. Login to the telnet using the administrator account. Use the command to list the library loaders of the AS (see man LL for help).

 

 

If you see your library listed with library: prefix then it was successfully deployed to the server.

 

Creating JSF 2.0 Dynamic Web Project

 

Now we are ready to create and deploy the web module of our application which will use the above Mojarra library and Primefaces UI componet library.

First we need to create a User Library in NWDS with the javax.faces-2.1.7.jar, this will be needed during JSF Facet selection of our Web project. For this, go to Preferences --> Java --> Build Path -->User Libraries and create new user library adding the Mojarra JAR to it.

 

 

 

Create new Dynamic Web Project. In the Configuration group, choose Default Configuration for SAP Libraries and click Modify button. Add JavaServer Faces 1.2 facet to the project (we will later change the JSF version by hand). Do not forget to add the Web project to the EAR project created in part 1 (tmp~sflight~ear).

 

 

 

When prompted to specify JSF capabilities, deselect the SAP Component Library for JSF and select the Mojarra user library you've created previously. This is needed only for compilation (access to javax.faces.context.FacesContext, etc), since at runtime it is the library deployed on the AS that will be used.

 

 

Once the project has been created it should have the following structure (with some of the files which will be added later) :

 

 

 

The project needs to reference the EJB and Java modules created in part 1. For this go to the project Properties --> Java EE Module Dependencies and select the EJB and Java modules. Now the Web module should have compile-time access to EJBs and DTOs.

 

 

We need to modify the web.xml file.

 

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>tmp~sflight~web</display-name>

<!-- Configure listener for Spring web application context -->

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

<!-- Your default application web page, index.xhtml, for example, see example below -->

    <welcome-file-list>
        <welcome-file>layout.xhtml</welcome-file>
    </welcome-file-list>

<!-- Faces servlet and mapping of xhtml pages -->

    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>

</web-app>

 

The only non-standard entry in this file is the reference to Spring's web application context loaded from the WEB-INF/applicationContext.xml. This file contains the jndi-lookup reference to the local stateless session EJB from the tmp~sflight~ejb project which will be deployed in the same EAR. We can find the exact JNDI name of the EJB using the technique described in part 1.

 

applicationContext.xml

 

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
    <!--
        Look up JraManagerBean EJB from the the JNDI    
     -->
    <jee:jndi-lookup id="jraManager"
        jndi-name="unil.ch/tmp~sflight~ear/LOCAL/JraManagerBean/ch.unil.sflight.ejb.JraManagerLocal" />

</beans>

 

 

We now modify faces-config.xml file to manually set the version of JSF to 2.0.

 

faces-config.xml

 

<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
    version="2.0">

<!-- application, converters, etc... -->

</faces-config>

 

We now are ready to create some views (xhtml pages) and corresponding JSF managed beans. For example, SearchFlights.java is shown below

 

//JSF 2.0 allows for annotation-driven specification of managed beans
@ManagedBean
@SessionScoped
public class SearchFlights implements Serializable {
    private static final long serialVersionUID = 1L;
    private static final Location loc = Location
            .getLocation(SearchFlights.class);

//we need to manually retrieve this bean from the application context, see init() method
    private transient JraManagerLocal jraManager;

    private String airlineId;
    private String destFrom;;
    private String destTo;
    private Collection<FlightData> flights;

//getters and setters are omitted

//will be executed once the bean has been initialized
    @SuppressWarnings("unused")
    @PostConstruct
    private void init() {
        jraManager = Utils.getBean("jraManager", JraManagerLocal.class);
    }

//action event called from the view
    public void search(ActionEvent event) {
        SimpleLogger
                .trace(
                        Severity.DEBUG,
                        loc,
                        "Search for flights with airlineId {0}, destFrom {1}, destTo {2}",
                        (Object) airlineId, (Object) destFrom, (Object) destTo);
        try {
            flights = jraManager.searchFlights(airlineId, destFrom, destTo);
            SimpleLogger.trace(Severity.DEBUG, loc, "Found {0} flights ",
                    (Object) flights.size());
            if (flights.size() == 0) {
                FacesContext.getCurrentInstance().addMessage(
                        null,
                        Utils.makeFacesMessage(FacesMessage.SEVERITY_INFO,
                                "info", "no_flights_found"));
            }
        } catch (BapiException e) {
            flights = null;
            Utils.processBapiErrors(e, loc);
        }

    }

}

 

The reference to the EJB has to be wired manually since we have chosen to let the JSF manage the scope of our beans, and so we cannot use @Autowired mechanism of Spring DI. You might be asking why didn't I just annotated the EJB reference with @EJB annotation, following the standard pattern. The problem is that when we deploy the EAR we will see the following error (which can be ignored).

 

Text:
May 2, 2012 3:20:32 PM com.sun.faces.spi.InjectionProviderFactory getProviderFromEntry
SEVERE: JSF1051: Service entry 'com.sap.faces.injection.InjectionProvider' does not extend DiscoverableInjectionProvider.  Entry will be ignored.

 

This error is expected since, the com.sap.faces.injection.InjectionProvider registered with Mojarra JSF 2.0 implementation does work with the default mechanism for EJB injection provided by the AS out of the box and configured for JSF 1.2. But to retrieve a been from the Spring's web application context is rather simple in the context of the JSF managed bean, we can use org.springframework.web.context.support.WebApplicationContextUtils for this purpose.

 

Utils.java

 

public class Utils {

    /**
     * Retrieves a bean with id given by <code>beanName</code> from current {@linkplain WebApplicationContext}.
     * @param <T> any type
     * @param beanName id of the bean
     * @param beanClass type of the bean
     * @return typed bean from the application context
     * @throws IllegalStateException if application context could not be retrieved
     * @throws BeansException if the bean with the given id could not be found
     * @throws ClassCastException if the retrieved bean cannot be cast to the provided type
     */
    public static <T> T getBean(String beanName, Class<T> beanClass) {
        WebApplicationContext appContext = WebApplicationContextUtils
                .getWebApplicationContext((ServletContext) FacesContext
                        .getCurrentInstance().getExternalContext().getContext());

        if (appContext == null) {
            throw new IllegalStateException(
                    "Cannot retrieve Spring web application context");
        }

        return beanClass.cast(appContext.getBean(beanName));
    }
}

 

Adding Primefaces UI component library

 

The real added value of all the work done above, comes with the ability to use third-party UI component libraries for JSF 2.0 framework. There is multitude of them, most of them are free or open-source and they allow for high quality, professional UI creation based on some leading edge client side scripting technology available. This not to mention the obvious advantages of using JSF 2.0 with it's improvements to navigation, AJAX support, and Facelets.

 

To add Primefaces UI components library, you normally just need to add it to the set of Web App Libraries of the Web Project located in WEB-INF/lib directory. I've tried with primefaces-3.2.jar but got a following error during deployment.

 

Text:
[JLinEE reported following erros for unil.ch/tmp~sflight~ear application.
ERRORS:
 * JSF Application Test: cvc-complex-type.2.4.a: Invalid content was found starting with element 'source-class'. One of '{"http://java.sun.com/xml/ns/javaee":system-event-listener-class}' is expected., file: tmp~sflight~web.war#META-INF/faces-config.xml, column 27, line 17

 

Apparently, the AS cannot validate the faces-config.xml packaged with the Primefaces JAR. But this is relatively easy to correct. You need to extract the contents of the primefaces-3.2.jar archive and edit the META-INF/faces-config.xml file. It need to be valid with respect to the declared javaee schema. This is just a matter of rearranging the order of some elements, for example, a system-event-listener element on the line 16 is

 

<system-event-listener>
    <source-class>javax.faces.application.Application</source-class>
    <system-event-class>javax.faces.event.PostConstructApplicationEvent</system-event-class>
    <system-event-listener-class>org.primefaces.webapp.PostConstructApplicationEventListener</system-event-listener-class>
</system-event-listener>

 

but should instead be

 

<system-event-listener>
    <system-event-listener-class>org.primefaces.webapp.PostConstructApplicationEventListener</system-event-listener-class>
    <system-event-class>javax.faces.event.PostConstructApplicationEvent</system-event-class>
    <source-class>javax.faces.application.Application</source-class>
</system-event-listener>

 

Once the validation errors are corrected, you can repackage the contents of the Primefaces JAR, which is now ready to be included as part of Web App Libraries of the project. To test if Primefaces are working you can use a simple index.xhtml page. If everything works well, you will be able to see the spinner UI component.

 

index.html

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">

    <h:head>
    </h:head>

    <h:body>
        <p:spinner />
    </h:body>

</html>

 

One more thing is needed for Primefaces to work on the AS. As Ingo mentions at the end of this forum post, we need to set the CompressedOthers property of HTTPProvider to false. Otherwise Primefaces will hung (until the connection timeout) trying to access some resources. For this login to /nwa interface with administrator, go to Configuration --> Infrastructure --> Java System Properties. Select Services tab and search for HTTP Provider. Set the CompressedOthers property to false (if needed). You might need to restart the AS for the changes to take effect.

 

Deploying the application

 

Before you deploy and run the application, you need to reference Mojarra JSF 2.0 library we deployed on the AS in the EAR's application-j2ee-engine.xml file.

 

<application-j2ee-engine>

    <!-- 
        This is the reference to the JSF 2.0 library,
        notice the prepend="true"
    -->

    <reference reference-type="hard" prepend="true">
        <reference-target provider-name="local.j2ee"
            target-type="library">javax~faces~2.1.7</reference-target>
    </reference>

    <!-- 
        This is only needed if you use com.sap.mw.jco.jra.ResultMap
        in tmp~sflight~java, see part 1
     -->

    <reference reference-type="hard">
        <reference-target target-type="application"
            provider-name="sap.com">tc~bl~jra~api</reference-target>
    </reference>

    <!-- 
        Cange to match your provider name
     -->

    <provider-name>unil.ch</provider-name>

</application-j2ee-engine>

 

At this point, it is likely that NWDS will complain that the XML file is invalid. You can disregard the error, but if you want to remove it, you can add an inline DTD declaration with prepend attribute specified as legal attribute of reference element.

 

<!DOCTYPE application-j2ee-engine [
<!ELEMENT application-j2ee-engine (reference*, classpath?, provider-name?, modules-additional?, fail-over-enable?)>

<!ELEMENT reference (reference-target)>
<!ATTLIST reference reference-type (hard|weak) #REQUIRED>
<!ATTLIST reference prepend (true|false) #IMPLIED>
<!ELEMENT reference-target (#PCDATA)>
<!ATTLIST reference-target target-type (application|library|service|interface) #REQUIRED>
<!ATTLIST reference-target provider-name CDATA #IMPLIED>

<!ELEMENT classpath (#PCDATA)>

<!ELEMENT provider-name (#PCDATA)>

<!ELEMENT modules-additional (module+)>
<!ELEMENT module (entry-name, container-type+)>
<!ELEMENT entry-name (#PCDATA)>
<!ELEMENT container-type (#PCDATA)>

<!ELEMENT fail-over-enable EMPTY>
<!ATTLIST fail-over-enable mode (disable|on_request|on_attribute) #REQUIRED>
]>

 

Once you've deployed the application, you should check the loaders for the application using telnet interface.

 

 

The reference to the library:local.j2ee~javax~faces~2.1.7 should be listed in the list of Direct Parent Loaders, and it should figure above the EAR's library loader, since we specified the prepend="true" in the application-j2ee-engine.xml file for this reference.

 

Summary of part 2

 

You should now have a working JSF 2.0 web application with Primefaces. You can use JQuery Themeroller to create a custom theme for the UI components of Primefaces which goes well with SAP look-and-feel. I'll try to add some screenshots of the application running on the AS portal soon.

This is the first of a series of posts describing a proof-of-concept application for NetWeaver 7.3 JEE application server using some popular Java development frameworks: Spring, JSF 2.0, and Primefaces. It is not intended to be used as is for any practical purpose, but instead can serve as a guide to using these frameworks on the SAP Java AS. The application uses Spring CCI temlpate to communicate with the back-end via JRA adapter, with the RFC calls executed within EJB session facade (thus allowing for the container-managed transactions), and with the user interface implemented as JSF 2.0 (Mojarra 2.1.7) web application with Primefaces. The application uses the standard SAP demo package for flight booking on the ABAP back-end.

 

Now available part 2 and part 3 of the series. Source code is available on Code Exchange project jsf20-nw73-showcase.

 

Requirements for the implementation of the application:

  • Administrator access to the NetWeaver administrator interface of AS
  • SSH connection to AS (sfp, telnet)
  • Back-end user capable to execute BAPI calls and working knowledge of SAP GUI client (SE37)
  • Familiarity with NetWeaver Developer Studio (EAR, EJBs, Web)
  • Working knowledge of Spring framework and JSF 2.0

 

Setting up JCA factory using JRA resource adapter

 

We need to make sure that we have the relevant flight data in the back-end tables. If necessary, the sample data for the flights can be generated on the back-end with SAPBC_DATA_GENERATOR program, which can be launched via SE38 transaction.

 


 

Once we have the data, we need to set-up the communication with the back-end. For this we will use the Java Resource Adapter deployed on the AS.

NW 7.3 has a JRA adapter deployed by default. What we need is to set-up a JCA connection factory (using the JRA resource adapter) which will be later looked up from the JNDI and used to create CCI connections to the back-end.

 

To create the JCA connection factory login to /nwa as the administrator, go to Configuration --> Infrastructure --> Application Resources. Search and select SAPJavaResourceAdapter15 entry. In the Resource Details pane, select Related JCA Resource and click on JCA Resource Details button.

 

 

Select eis/SAPJRAFactory and click on Copy and Add New Connection Factory. Chose an appropriate factory name (for example, eis/BAS_SAPJRAFactory, where BAS is for the system ID of the back-end sever). We now need to configure the connection properties for the factory we just created. Enter connection pooling properties which determine the maximum number of connections to be created by this factory and the maximum idle time for each connection.

 

 

In the configuration properties we enter the parameters relevant to the back-end server: username, password, client number, which will be used in the JCo connections used by JRA.

 

 

 

Java module with Spring CCI support

 

We now are ready to create our application in NWDS. Normally, the application should be a collection of Development Components (DCs) taking advantage of NetWeaver DI, but for the sake of simplicity we will create a standalone EAR application. Create a simple Java Project (tmp~sflight~java). Then create an Enterprise Application Project (tmp~sflight~ear). Leave default target runtime (SAP Libraries), EAR version (5.0), and configuration (Default Configuration for SAP Libraries). Important: when prompted, select tmp~sflight~java as Java EE module dependencies, this will add all the necessary SAP JEE libraries as well as the EAR libraries from /tmp~sflight~ear/EarContent/lib directory to the classpath of the Java project.

 

We need to add Spring compile and runtime dependencies to our EAR project. Use your preferred way to get them. I used Apache Ivy to get all the dependencies for the org.springframework:spring-context:3.1.RELEASE version. Add these libraries to /tmp~sflight~ear/EarContent/lib directory, this way they will be deployed with our application archive and will be automatically available on the classpath of our Java, EJB, and Web modules, as well. The EAR project setup should look as following:

 

 

 

And the Java project as follows:

 

 

 

Notice that there is one more library (sap.com~tc~bl~jra~RUNTIME.jar) which I added to the build path of the Java project manually. This is needed optionally to be able to take advantage of the SAP's com.sap.mw.jco.jra.ResultMap extension of javax.resource.cci.MappedRecord interface. The library for this API is normally configured as a dependency to the api public part of the tc/bl/jra/api DC of ENGFACADE SC, but since we are not using DCs, we can use the equivalent library found on the AS itself (just login with SSH and run locate tc~bl~jra to see where exactly it is located). Alternatively, you can create a simple DC with this dependency and get the jar file by browsing the workspace .jdi directory once the DC is built. The rest of this post does not have any references to this API.

 

The idea is to be able to use JCA CCI support of the Spring library in order to greatly facilitate the interaction with the JRA adapter, managing connections, executing BAPI calls, etc.

 

The following will explain how we can call BAPI_FLIGHT_GETLIST BAPI in the back-end and get the list of the flights by the airline ID. Create a simple Java DTO object which will contain flight information.

 

public class FlightData implements Serializable {
    private String airlineId;
    private String airlineName;
    private String connectId;
    private Date flightDate;
    private String airportFrom;
    private String cityFrom;
    private String airportTo;
    private String cityTo;
    private Time departureTime;
    private Time arrivalTime;
    private Date arrivalDate;
    private BigDecimal price;
    private String currency;

//getters and setters

}

 

This corresponds to the data object BAPISFLDAT used by ABAP for the FLIGHT_LIST output table for this BAPI.

 

 

Then we need an extension of org.springframework.jca.cci.object.MappingRecordOperation as follows:

 

public class BapiFlightGetListOperation extends
        MappingRecordOperation {

//Location object for SAP logger
private static final Location loc = Location.getLocation(BapiFlightGetListOperation.class);

    public BapiFlightGetListOperation(ConnectionFactory connectionFactory) {
        super(connectionFactory, null);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected Record createInputRecord(RecordFactory recordFactory, Object obj)
            throws ResourceException, DataAccessException {
        Object[] input = (Object[]) obj;
        SimpleLogger.trace(Severity.DEBUG, loc, "Record inputs: "
                + Arrays.toString(input));
        MappedRecord record = recordFactory
                .createMappedRecord("BAPI_FLIGHT_GETLIST");
        // TODO: set other input parameters
        if (input[0] != null) {
            record.put("AIRLINE", ((String) input[0]).toUpperCase());
        }
        return record;
    }

    @Override
    protected Object extractOutputData(Record record) throws ResourceException,
            SQLException, DataAccessException {
        Object obj = null;
     //custom method to see if BAPI returned with errors
        Bapiret2[] errors = checkForBapiErrors(((MappedRecord) record),
                "RETURN");
        if (errors.length == 0) {
            ArrayList<FlightData> flights = new ArrayList<FlightData>();
            ResultSet cursor = (ResultSet) ((MappedRecord) record)
                    .get("FLIGHT_LIST");
            while (cursor.next()) {
                flights.add(readFlightData(cursor));
            }
            obj = flights;
        } else {
            obj = errors;
        }
        return obj;
    }

private Bapiret2[] checkForBapiErrors(MappedRecord record,
            String bapiretTableName) throws SQLException, DataAccessException {

 //omitted for clarity

    }

    private FlightData readFlightData(ResultSet cursor) throws SQLException {
        FlightData data = new FlightData();
        data.setAirlineId(cursor.getString("AIRLINEID"));
        data.setAirlineName(cursor.getString("AIRLINE"));
        data.setConnectId(cursor.getString("CONNECTID"));
        data.setFlightDate(cursor.getDate("FLIGHTDATE"));
        data.setAirportFrom(cursor.getString("AIRPORTFR"));
        data.setCityFrom(cursor.getString("CITYFROM"));
        data.setAirportTo(cursor.getString("AIRPORTTO"));
        data.setCityTo(cursor.getString("CITYTO"));
        data.setDepartureTime(cursor.getTime("DEPTIME"));
        data.setArrivalTime(cursor.getTime("ARRTIME"));
        data.setArrivalDate(cursor.getDate("ARRDATE"));
        data.setPrice(cursor.getBigDecimal("PRICE"));
        data.setCurrency(cursor.getString("CURR"));
        return data;
    }

}

 

This implementation will create an instance of Spring's MappingRecordOperation class using passed javax.resource.cci.ConnectionFactory instance. The implementation of the method createInputRecord() is responsible for specifying BAPI's input values. And the method extractOutputData(), for extracting the output and storing it in the DTO object. Finally, here is the extension of org.springframework.jca.cci.core.support.CciDaoSupport which is responsible for creating the instance of BapiFlightGetListOperation and executing the BAPI with actual parameters.

 

public class JraDao extends CciDaoSupport {
      //custom extension of MappingRecordOperation
    private BapiFlightGetListOperation flightGetListOp;

     //connecionFactory will be injected via DI, see context configuration
    @Override 
    protected CciTemplate createCciTemplate(ConnectionFactory connectionFactory) {
        CciTemplate cciTemplate = super.createCciTemplate(connectionFactory);
        flightGetListOp = new BapiFlightGetListOperation(connectionFactory);
        return cciTemplate;
    }

     //executes MappingRecordOperation with actual parameters
    public Object searchFlights(String airlineId,
            String destFrom, String destTo) {
        return flightGetListOp.execute( new Object[]{airlineId, destFrom, destTo});
    }

}

 

All of this Spring magic comes together of course through application context configuration file. The following section deals with the configuration of the EJB project which will serve as a session facade to the JSF webapp, and which is responsible for instantiation of org.springframework.context.support.ClassPathXmlApplicationContext needed for the communication layer to work.

 

EJB project and common application context

 

Create an EJB Project (tmp~sflight~ejb) leaving all default options, do not forget to add it to the tmp~sflight~ear EAR project as JEE module. Also specify a reference to tmp~sflight~java Java project so that the EJBs have access to the DTOs.

 

 

 

The idea is to be able to delegate to Spring the creation of the JraDao instance (described above) with an instance of JCA connection factory looked up from JNDI of the AS and inject it into our session bean. We can use Spring's EJB 3 Injection interceptor which automatically instantiates the beans found in the special context file, beanRefContext.xml (available on the classpath, see Java project setup).

 

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 
        Specify the list of application contexts to be loaded and shared by all
        the WAR and EJB modules in the EAR. All the beans from these contexts
        can be made available to the EJBs via
        @Interceptors(SpringBeanAutowiringInterceptor.class) class level annotation.
        To reference the beans from these contexts in a WAR module use
        usual Spring mechanism for bootstrapping web application context with 
        "parentContextKey" context parameter set to "earContext"
        (value of the bean's "id" attribute below.)
     -->
    <bean id="earContext"
        class="org.springframework.context.support.ClassPathXmlApplicationContext">
        <constructor-arg>
            <list>
                <value>common-context.xml</value>
            </list>
        </constructor-arg>
    </bean>

</beans>

 

The beans declared in the context file common-context.xml (from Java project) are then not only available to be injected into the EJBs but also can be referenced from WAR web application context of the same EAR, as well. Here are the contents of the common-context.xml file :

 

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">

    <!-- 
        Configure logging for Spring classes with Log4j logger and
        a custom appender for SAP com.sap.tc.logging.Location.
        For this to work log4j.properties file needs to be packaged
        with the EAR module together with the Spring's libraries
        and the custom appender implementation.
     -->
    <bean
        class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
        p:targetClass="org.springframework.util.Log4jConfigurer"
        p:targetMethod="initLogging">
        <property name="arguments">
            <list>
                <value>classpath:log4j.properties</value>
            </list>
        </property>
    </bean>

    <!-- 
        Look up JRA adapter bean from JNDI registry on the AS.
     -->
    <jee:jndi-lookup id="eisSapJraConnectionFactory"
        jndi-name="deployedAdapters/eis/BAS_SAPJRAFactory/shareable/eis/BAS_SAPJRAFactory" />

    <!-- 
        DAO object using CCI API to work with JRA adapter.
        If no reference to ConnectionFactory is specified then
        MappingRecordOperation references should be wired
        manually.
     -->
    <bean id="jraDao" class="ch.unil.sflight.java.jra.JraDao"
        p:connectionFactory-ref="eisSapJraConnectionFactory" />

    <!-- 
        Autowire Spring dependencies into EJBs.
     -->
    <context:component-scan base-package="ch.unil.sflight.ejb" />

</beans>

 

Note that we are using jee:jndi-lookup tag as a convenient way to lookup the JCA factory from the JNDI context. The JNDI name of the factory can be found as following. Login to /nwa as the administrator, go to Troubleshooting --> JNDI Browser. Search for the object with the same name as the one used when configuring JCA connection factory (see above).

 

 

Select the shareable resource, the Object Name is the JNDI name which should be specified in the jee:jndi-lookup. Using Spring's context:component-scan mechanism, we can now autowire the JraDao instance into our session bean.

 

//annotation needed to bootstrap context from beanRefContext.xml
@Interceptors(SpringBeanAutowiringInterceptor.class)
@Stateless
//annotation needed for context:component-scan to work
@Component
public class JraManagerBean implements JraManagerLocal {

     //autowired by context:component-scan
    @Autowired
    private JraDao jraDao;

     //business method 
    @SuppressWarnings("unchecked")
    @Override
    public Collection<FlightData> searchFlights(String airlineId,
            String destFrom, String destTo) throws BapiException {
        Object obj = jraDao.searchFlights(airlineId, destFrom, destTo);
        if (obj instanceof Bapiret2[]) {
            throw new BapiException("BAPI returned with an error", (Bapiret2[]) obj);            
        }
        return (Collection<FlightData>)obj;
    }

}

 

Note the use of Interceptors and Component class-level annotations.

 

Summary of part 1

 

What we have achieved so far is to create a session facade with an EJB which uses Spring interceptor to autowire a reference to a JCA connection factory configured on the AS to use a JRA adapter to communicate to the ABAP back-end. We then use a convenient way to execute BAPI calls via Spring's CCI API and the connection factory obtained from JNDI context. Next part will discuss the setup of the JSF 2.0 front-end with the popular Primefaces library.

 

Some useful links below:

 

Spring Integration on SAP NetWeaver

This year, SAP is again sponsoring and participating in the Open Source Business Conference (OSBC), which is scheduled for May 21-22 in San Francisco, California. The conference is centered around three major themes that SAP - no real suprise here - has already been focusing on for quite some time: mobile, big data and cloud computing. In the different conference tracks, it will be explored how open source software and open source development principles support key innovations in these areas.

 

For SAP it will be interesting to find ways on how to combine key SAP technology innovations with relevant open source technologies to eventually utilize innovation from the open source community and create more complete solutions for our customers. In this regard, we are preparing a demo how SAP HANA can interoperate with key open source technologies such as Hadoop and R. While Hadoop is gaining traction in the industry, one scenario to explore further is how to enable the growing number of data nodes that support the Hadoop Distrbuted File System to act as a data source in HANA. Having a common and reliable approach on how to implement this scenario might be of interest to customers in various industries. As for R, there is already quite some interest and experimentation on the In-Memory Business Data Management and SAP HANA space on how to make use of R (the language) and its statistical and data mining features. The interesting fact about R is that many end users (mostly statisticians) share and co-develop many packages that include algorithms for specific purposes. Allowing these packages and the statisticians' skill sets to be reused in an SAP context does make a lot of sense and will represent the second part of the demo. Please note that both integration scenarios are still in an experimentation phase, but we are looking for interest and feedback from SAP and non-SAP users.

 

Also, together with Steve George, General Manager, Canonical and Paolo Juvara, CEO, Openbravo, I will participate in a panel on Success Factors for Enterprise Open Source Adoption. We want to explore how end-user organizations are adopting open source - pretty much along the lines of what I recently presented in my webinar on the same topic.

 

So, if you are interested to come to OSBC as well, attend the various sessions and meet the SAP gang, please let me know at claus dot von dot riegen at sap dot com - I have a few free tickets still avaiable.

It’s been a while since I did my last Open Source - from whitespace to Black Duck on open source and I thought that now is a good time to reflect on what we experienced, learned and changed in the way we adopt open source software at SAP. Being a vendor of enterprise applications comes with a number of responsibilities since customers expect – in addition to the right functional scope - a clear commitment to usability, quality, reliability, and, last but not least, security. So, essentially the same commitment needs to cover open source products we integrate into our product portfolio or choose to interoperate with. What this actually means and how we are able to execute on this commitment is something I’d like to explain in a webinar on February 14th. Please register at https://www1.gotomeeting.com/register/868421529, join the session and feel free to participate in the Q&A session – more than explaining our way, I’d also like get your feedback and to hear about your own experience.

Filter Blog

By author: By date:
By tag: