Freitag, 12. Oktober 2012

Cross domain request & Jersey. And IE9 caching ajax problem solution (304 not modified).


Cross domain request & Jersey. And IE9 caching ajax problem solution (304 not modified).

In our pretty cloud world cross domain requests are common practise. Web applications consume code across CDNs and several other sources. So the good old "same domain policy" is definitely out-dated. There are many solutions to that thing.. like JSONP. But the finest solution allowing open access across all boundaries come with the CORS Specs by W3C  (see http://enable-cors.org/)

You'll find a lot of discussions about Jersey & CORS at the following blogs:

Basic Coding Ideas

http://blog.kdecherf.com/2011/06/19/java-jersey-a-cors-compliant-rest-api/

http://2rdscreenretargeting.blogspot.de/2012/06/enable-cors-for-jersey.html


The Solution: Jersey and CORS

http://software.dzhuvinov.com/cors-filter-configuration.html

A sample web.xml with CORS support for Jersey:

    <filter>
        <filter-name>CORS</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
        <init-param>
            <param-name>cors.allowOrigin</param-name>
            <param-value>*</param-value>
        </init-param>
        <init-param>
            <param-name>cors.supportedHeaders</param-name>
            <param-value>origin, content-type, accept</param-value>
        </init-param>
        <init-param>
            <param-name>cors.allowGenericHttpRequests</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>cors.supportedMethods</param-name>
            <param-value>GET, POST, HEAD, PUT, DELETE</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CORS</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>




IE9 is even caching Ajax GET request.

Something a developer wouldnt except happens at Microsofts IE9: its caching AJAX GET requests. In the developer console an ajax GET request response with 304 (not modified), but have tested it, IE9 never touches the server resource in that case. So the 304 Header is a misleading information, because your Jersey Server was never called by IE9 and in fact was never sending an 304 response.  Its all about the caching behaviour of IE9.

To get rid of that, the best solution is to send a "Cache-Control: no-cache" Header with your GET/POST/etc responses. You can use ContainerResponseFilters within Jersey to automatically add "no caching" to every response. Normally caching f.e. JSON data client-side doesnt make sense at all.

To avoid browsers caching your responses, your web.xml file cloud make use of ContainerResponseFilters:

        <init-param>
            <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
            <param-value>here.you.point.to.a.filter.class</param-value>
        </init-param>



A sample class look like:


public class HttpHeaderFilter implements ContainerResponseFilter {

    @Override
    public ContainerResponse filter(ContainerRequest req, ContainerResponse contResp) {

        Response.ResponseBuilder resp = Response.fromResponse(contResp.getResponse());
        resp.header("Cache-Control","no-cache");
        contResp.setResponse(resp.build());
        return contResp;
    }

}


Thanks to Dean Moses for his worthful information about IE9 Caching:

http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/

Sonntag, 23. September 2012

IntelliJ IDEA 11 - Setup multiple instances of Tomcat on Windows as service



Preparation

In this short tutorial i suppose you have already installed a tomcat server on your local machine. Otherwise download and install TomCat 7 here: http://tomcat.apache.org/

Part I: Install a new instance of TomCat


Steps

1. Assuming you have installed TomCat to C:\TomCat 7.0\, then copy the complete folder to C:\TomCat 7.0-2\ for example.


2. Navigate to C:\TomCat 7.0-2\bin\ and edit the server.xml file.

3. Change all ports (Shutdown-Port, Connector-Port, Redirect-Port and AJP Connector) in the server.xml configuration file. I except you know what a port is, so use free ones.

4. In the final setp we'll register tomcat7 as windows service. I prepared a short batch file to shorten the process... create a batch file within C:\TomCat 7.0-2\ and execute it via cmd.exe. But be aware, this will only work, if you start the command line with administrator privileges!

"C:\Tomcat 7.0-2\bin\tomcat7.exe" //IS//Tomcat6 --DisplayName="Apache Tomcat 7.0-Instance 2" --Install="C:\Tomcat 7.0-2\bin\tomcat7.exe" --Jvm=auto --StartMode=jvm --StopMode=jvm --StartClass=org.apache.catalina.startup.Bootstrap --StartParams=start --StopClass=org.apache.catalina.startup.Bootstrap --StopParams=stop


You are done!

Part II: Configure IntelliJ


In the second part we ll tell IntelliJ to use the new TomCat instance.

Steps

1. Click "Edit run/debug configuration"

2. Add a new TomCat -> Local configuration.

3. Important: On the first page of the configuration settings you ll find a combo called "Application Server". Click "Configure.." and add the new TomCat instance by giving the new home directory.

4. Then change the URL and ports configuration.

5. You are done.


Now you can use two different TomCat instances within IntelliJ. Makes debugging f.e. serveral web services totally easy;)





Samstag, 22. September 2012

SAPUI5 with IntelliJ IDEA 11


Setting up SAPUI5 with IntelliJ IDEA 11 - Tutorial

Steps

1. Click File -> New Project.. 

2. Use the wizard to create a new Maven Project. So far SAPUI5 is not available through a maven repository. How ever, i use maven for further purposes and aditional libraries.

3. Then select the project root element, right click and select Add Framework Support..

4. Select "Web" and continue. Now a "web" folder will be added to your project.

5. Right click the project root and create new folder. Name it "lib". Here we'll store all SAPUI5 related libraries.

Okay.. how to get the SAPUI5 jars? I suggest you download SAPUI5 from sap's SCN homepage. See here: http://scn.sap.com/community/developer-center/front-end

5.1 Extract the zip file called HTML5Evaluation_complete.zip. After that, you ll find a folder called "tools-updatesite". Within the folder there is another one, called "plugsins".

5.2 Copy all .jar files starting with "com.sap.ui5" into your recently created "lib" folder.

6. Open the Project Settings within IntelliJ and open "Libraries". Then pres the [+] button and add all SAPUI5 related .jar files to your project. I know... myself wasnt able to select all items at once and add them.. i think we have to go the hard way and have to add every single .jar...

Done this, your libraries settings should look like this:



7. Then switch to "Artifacts", select all available elements, right click -> Put into WEB-INF\lib

Then you should see something like this:



Caution!  Dont add "com.sap.ui5.ressource.osgi_1.4.3.jar to your Web-Inf\lib folder. The .jar has a dependency to osgi 1.4.3 (this is an mistake in the above screenshot). If you add this library you end up with an missing dependency (osgi 4.3).

8. Edit your web.xml file and copy the following snippet into your own web.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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-app_2_5.xsd"
         version="2.5"
         xmlns="http://java.sun.com/xml/ns/javaee">

    <display-name>testSAPViews</display-name>

    <!-- ============================================================== -->
    <!-- UI5 resource servlet used to handle application resources      -->
    <!-- ============================================================== -->

    <servlet>
        <display-name>ResourceServlet</display-name>
        <servlet-name>ResourceServlet</servlet-name>
        <servlet-class>com.sap.ui5.resource.ResourceServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ResourceServlet</servlet-name>
        <url-pattern>/resources/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>ResourceServlet</servlet-name>
        <url-pattern>/test-resources/*</url-pattern>
    </servlet-mapping>
    <!-- BEGIN: DEV MODE -->
    <context-param>
        <param-name>com.sap.ui5.resource.DEV_MODE</param-name>
        <param-value>true</param-value>
    </context-param>
    <!-- END: DEV MODE -->


    <!-- ============================================================== -->
    <!-- Cache Control Filter to prevent caching of any resource        -->
    <!-- ============================================================== -->

    <filter>
        <display-name>CacheControlFilter</display-name>
        <filter-name>CacheControlFilter</filter-name>
        <filter-class>com.sap.ui5.resource.CacheControlFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CacheControlFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>CacheControlFilter</filter-name>
        <url-pattern>*.js</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>CacheControlFilter</filter-name>
        <url-pattern>*.xml</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>CacheControlFilter</filter-name>
        <url-pattern>*.json</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>CacheControlFilter</filter-name>
        <url-pattern>*.css</url-pattern>
    </filter-mapping>


    <!-- ============================================================== -->
    <!-- UI5 proxy servlet                                              -->
    <!-- ============================================================== -->

    <servlet>
        <servlet-name>SimpleProxyServlet</servlet-name>
        <servlet-class>com.sap.ui5.proxy.SimpleProxyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SimpleProxyServlet</servlet-name>
        <url-pattern>/proxy/*</url-pattern>
    </servlet-mapping>


    <!-- ============================================================== -->
    <!-- Welcome file list                                              -->
    <!-- ============================================================== -->

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>


</web-app>


9. Within the project folder "web" you ll find the file "index.jsp". Delete this file and create a new file named "index.html". As you can see the "welcome-file" within web.xml is set to index.hml.  Otherwise change this setting.


You're done with setting up SAPUI5 for IntelliJ IDEA 11. Now its time to continue coding...

Bye the way.. if you reading this lines and you are working for SAP, i have to state my full respect for SAPU5 and your development guys. Its a planet shaking product... its soooo made in germany;)


Dienstag, 18. September 2012

Jersey consume JSON Example & Test with Postman



Jersey consume JSON Example & Test with Postman


Domain Class Example Code


@XmlRootElement
public class Test {

    private String Firstname;

    private String Lastname;

    public Test()
    {
    }

    public Test(String firstname, String lastname)
    {
        this.setFirstname(firstname);
        this.setLastname(lastname);
    }

    public String getFirstname() {
        return Firstname;
    }

    public void setFirstname(String firstname) {
        Firstname = firstname;
    }

    public String getLastname() {
        return Lastname;
    }

    public void setLastname(String lastname) {
        Lastname = lastname;
    }
}


Ressource Class Method


    @POST
    @Path("/set")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.TEXT_PLAIN)
    public String setTest(Test someName)
    {
        return "Hello "+ someName.getFirstname()+" nice to meet you.";
    }



Hints for using Chrome Plugin "PostMan"

1. Set Content-Type of http header to "application/json" (otherwise Jersey will answer with 415 Unsupported Media Type)

2. Send RAW message body in json format:

{"firstname":"baby","lastname":"miller"}

Jersey 1.9 with IntelliJ IDEA 11



Jersey 1.9 with IntelliJ IDEA 11

In this short tutorial we ll see how you can setup Jersey with IntelliJ IDEA 11. I have been new to IntelliJ IDEA so it took me a while to find it out. Here we go..

Development Environment
  • IntelliJ IDEA 11
  • TomCat 7
  • JDK7
Ressources

Steps

1. Create a new Maven Project in IntelliJ IDEA. Its not necessary to use an archetype of maven.

2. Right click on the project root and click "Add Framework Support", then check "Web" and continue. IntelliJ will add a "web" folder to your project.

3. Edit the pom.xml file an copy&paste the following dependencies for maven.


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>CXMService</groupId>
    <artifactId>CXMService</artifactId>
    <version>1.0</version>

    <dependencies>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.9</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-grizzly2</artifactId>
            <version>1.9.1</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>1.9</version>
        </dependency>
    </dependencies>
    
</project>

Note: In the Jersey documentation they recommend to use Version 1.9.18-i for Grizzly2; for now my installation wasnt able to resolve this dependency, so i took 1.9.1 and it worked.

4. Right click the pom.xml file and select Maven -> Reimport. Then the IDE will load all  libraries and shows them in "External libraries".

5. Setup "Tomcat" as your deployment plattform. To do so, click "Edit Configurations.." and setup TomCat. There is a nice PDF out in the wild, explaining how to setup your application server. See here.

6. Edit the web.xml within web/WEB-INF folder.

7. Copy&Paste the following code snippet to get Jersey running as serverlet. Alternate configurations can be found here.

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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-app_3_0.xsd"
           version="3.0">
    <servlet>
        <servlet-name>Jersey REST Service</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>cxm.spider.test</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey REST Service</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>

The web.xml will configure Jersey with JSON support. I marked in red two parameters you should change. Instead of "cxm.spider.test" give your package name, containing the root ressource classes (classes with @Path annotation). The url-pattern can be changed, its optional. Alternatives are i.e. /* or /myservice/*

8. Before you can deploy Jersey, open the Project Settings in IntelliJ IDEA (STRG-ALT-S) and navigate to "Artifacts".

9. Then select all available elements, right click and choose "Put in /WEB-INF/lib"

Now you should be able to start and deploy your service. But wait! The service is not yet finished. Its ready for deployment but it wont work before adding at least one ressource class (see Jersey documentation). If you miss out, the TomCat logs will show an  exception like "no ressource class found.".