At a customer site we are using Sonatype Nexus as a local Maven repository. It stores our own artifacts as well as binary third-party components. Nexus runs as a web application in Tomcat 6 behind an Apache 2.2 web server. Yesterday I had a very frustrating problem: it was impossible to deploy large files with deploy:deploy-file. Small files worked every time.
What to do? I tried all Apache and Tomcat options I could find that seemed relevant. I also configured Maven to use dav instead of http. That required the use of a local dummy pom:
<project> <modelVersion>4.0.0</modelVersion> <groupId>localdomain.localhost</groupId> <artifactId>dummy</artifactId> <version>1.0-SNAPSHOT</version> <build> <extensions> <extension> <groupId>org.apache.maven.wagon</groupId> <artifactId>wagon-webdav-jackrabbit</artifactId> <version>1.0-beta-7</version> </extension> </extensions> </build> </project>
With this in place and -DgeneratePom=true on the command line I could deploy to dav:http://server/path. Still no luck, though.
I finally found a solution. If Apache is configured to use keep-alives it works! Edit httpd.conf and set:
With this configuration it is possible to deploy large files both with dav and with plain http.
EJB3 web services are great. Simply slap on a @WebService annotation, deploy and it works. A few additional annotations can improve the interface. However, with WebLogic 11g the service endpoint becomes http://server:port/ClassName/ServiceName, where ClassName is the name of the session bean and ServiceName comes from the annotation. This is a bit ugly, the class name of the session bean is an implementation detail and should not be exposed.
Fortunately there is a solution and it keeps the code portable. First, define a generic webservices.xml file with the minimum required information for the web service:
<?xml version="1.0" encoding="UTF-8"?> <webservices xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2"> <webservice-description> <webservice-description-name>SomeService</webservice-description-name> <port-component> <port-component-name>SomeServicePort</port-component-name> <wsdl-port xmlns:ws="http://someserver.com/SomeService"> ws:SomeServicePort</wsdl-port> <service-endpoint-interface> com.someserver.ws.SomeServiceRemote </service-endpoint-interface> <service-impl-bean> <ejb-link>SomeService</ejb-link> </service-impl-bean> </port-component> </webservice-description> </webservices>
Then add a weblogic-webservices.xml file:
<?xml version = '1.0' encoding = 'UTF-8'?> <weblogic-webservices xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-webservices http://www.bea.com/ns/weblogic/weblogic-webservices/1.0/weblogic-webservices.xsd" xmlns="http://www.bea.com/ns/weblogic/weblogic-webservices"> <webservice-description> <webservice-description-name> SomeService </webservice-description-name> <webservice-type>JAXWS</webservice-type> <port-component> <port-component-name>SomeServicePort</port-component-name> <service-endpoint-address> <webservice-contextpath>/SomeService</webservice-contextpath> <webservice-serviceuri>/SomeOperation</webservice-serviceuri> </service-endpoint-address> <wsdl> <exposed>true</exposed> </wsdl> </port-component> </webservice-description> </weblogic-webservices>
This will bind the web service to the address http://server:port/SomeService/SomeOperation.
Oracle SOA Suite 11g makes it possible to use fault policies in order to catch and act on certain types of errors. This can be very useful and if the built-in actions are not enough it is possible to write custom actions in Java. See How to Use a Java Action Fault Policy in the Developer’s Guide.
Both the documentation and the API has room for improvement, though.
The documentation helpfully records that IFaultRecoveryJavaClass needs fabric-runtime.jar, but it fails to mention that orabpel.jar is needed as well for IBPELFaultRecoveryContext. Unfortunately the plain IFaultRecoveryContext interface is so limited that it is almost useless. It doesn’t even provide access to the fault. In order to be of use the context must be cast into a IBPELFaultRecoveryContext (for BPEL faults).
IFaultRecoveryContext does include a method named getProperties that returns the property set for the fault policy action. Does it return a Properties object? No, it returns a raw Map. Oh well, but surely it is a map from String to String? Same thing, right? Wrong. It returns a map from String to ArrayList. As nothing is documented I found that out with trial and error. Typically the first element in the list can be cast into a String and used.
Finally the documentation uses elements named ReturnValue in the fault policy, but the implementation uses returnValue.
I recently wrote an application for managed file transfers with FTP, FTPS and SFTP. Naturally I wanted good unit tests and I found an excellent solution that made it possible to run real transfers in a controlled way: MockFtpServer and Apache SSHD. This way I could fire up an FTP server and an SSH server from jUnit, run a test and be in full control over both the client (my application) and the servers.
The same approach can be used to test file-based integrations in general driven from jUnit, possibly with a continuous integration engine such as Jenkins running the tests.
To use the libraries with Maven, include:
<dependency> <groupId>org.mockftpserver</groupId> <artifactId>MockFtpServer</artifactId> <version>2.3</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.sshd</groupId> <artifactId>sshd-core</artifactId> <version>0.6.0</version> <scope>test</scope> </dependency>
You may need additional dependencies as well, for example SLF4J and BouncyCastle.