Thursday, December 16, 2010

Findbug - A useful tool for Java developer

Findbug is useful in developing a clean and efficient code if you are a java developer.

Go to the below link to know more about it.

http://findbugs.sourceforge.net/manual/eclipse.html

You can also use Findbug using maven by adding the plugin. But if you have a eclipse, you should prefer it that way.

Thursday, December 2, 2010

Steps to disable OOM Killer on Linux

OOM kills any process which has been waiting for a long time. But some times, we need to avoid this and make sure these long waiting processes are allowed to complete even if it takes much more time.
To disable OOM, follow the below steps.

Check status of oom-killer:

# cat /proc/sys/vm/oom-kill

Turn oom-killer off/on:
# echo "0" > /proc/sys/vm/oom-kill
# echo "1" > /proc/sys/vm/oom-kill

To make this change take effect at boot time, add the following
to /etc/sysctl.conf:
vm.oom-kill = 0

For processes that would have been killed, but weren't because the oom-
killer is disabled, you'll see the following message
in /var/log/messages:
"Would have oom-killed but /proc/sys/vm/oom-kill is disabled"

Monday, November 22, 2010

OID LDAP commands

Add users
./ldapadd -h hostname.company.com -p 389 -D cn=orcladmin -w passwd -f /home/oracle/software/New_Oid_Users.txt

Delete Users
./ldapdelete -h hostname.company.com -p 389 -D cn=orcladmin -w passwd -c -v -f /home/oracle/software/delete_users.txt

OIM: Installing the Design Console under Linux

Follow below URL, its a cool solution.

http://www.idmworks.com/blog/oim-installing-the-design-console-under-linux

It does work!!

Thursday, November 18, 2010

Make OIM portal load faster

Whenever a user tries to login to OIM admin console, OIM runs some additional SQL's to get the count of provisioning tasks, pending approvals etc, to display on the home page.
This can cause the home page to load slowly.

Since this information is not of much use in many organization on the home page, we can disable this additional SQL search and make sure only a link is placed on the home page to get to that same data.
To disable these counters, please execute below steps:

1) Login to Design Console with 'xelsysadm'

2) Go to Administration->> System Configuration

3) Search for the keyword "XL.WebAdminHome.CounterDisplay.Type"

4) Change the values from 'DayLimit' to 'CheckLink'

Now when a user logs in OIM he will see a link instead of counters.

For many users, the home page will be much faster from now on.

Special characters not allowed in name fields - OIM

The following fields in OIM do not support special characters:
  • User Login
  • Group Name
  • Organization Name
  • Resource Name
  • Process Name
  • Request Number
  • Column Label
  • Task Name
The following are the special characters that are not supported in the preceding fields:
  • Semicolon ( ; )
  • Pound ( # )
  • Forward slash ( / )
  • Percent ( % )
  • Equals sign ( = )
  • Bar ( | )
  • Plus sign ( + )
  • Comma ( , )
  • Back slash ( \ )
  • Double quotes ( " )
  • Less than ( < )
  • Greater than ( > )

If you are using your own form to create a user in OIM, make sure to restrict the above characters in the preceding fields.


The allowed special characters are as below :

! * @ $ ( ) ^ ? { } [ ] : ' ~ ` - _

Put these in a common regular expression pattern.

OIM user email field character restriction

If you are using OIM 9.0.1, then the user's email address field will only accept characters as defined in the below statement.

"The local-part and domain name portions of an e-mail address are restricted to ASCII letters, numbers, underscores, hyphens, and periods. The domain identifier portion of an e-mail address is restricted to ASCII letters and numbers"
(http://download.oracle.com/docs/cd/B32479_01/doc.903/b32455/componts.htm#CIHCCEAF)

But this restriction is removed in OIM 9.0.2 version. Below regular expression defined the characters allowed in the email address field in version 9.0.2

([\\w!#$%&'*+-/=?^_`{|}~])+[@](\\w|[-]|[.])+[.]([a-zA-Z0-9])+

So if you need all those special characters, you will have to make sure you are using 9.0.2 and not 9.0.1.

It is a patch update to upgrade from 9.0.1 to 9.0.2. So it should not be difficult.

Auto Approve Self Registered Users in OIM

By default, a self registered user will have to be approved by a administrator. To automatically approve Self Registered Users in OIM


1. Open the OIM_HOME/xellerate/config/FormMetadata.xml file.

2. Copy the following lines from <form name="SelfRegistrationApprovalForm"> to <form name="SelfRegistrationUserForm"> section:

<attributereference editable="true" optional="true">Organizations.Organization Name</attributereference>
<attributereference editable="true" optional="false">Users.Xellerate Type</attributereference>
<attributereference editable="true" optional="true">Users.Role</attributereference>

3. Save changes and restart the OIM Server.

4. Now when you try to do a Self Register, you need to enter values for Organization name, User Type and Employee Role.

5. Enter value for User Type as End-User.

6. Enter value for Employee Role as Full-Time (Note: The value should be Full-Time and not Full-Time Employee).

7. Submit request, and the request would get automatically approved.

New Blog for Identity Management

I have added a new blog which is dedicated for Oracle identity Management.

So if you are looking for any help of identity management, please check the below link.

http://identity-corp.blogspot.com/

Delete OID users and Groups

To delete all OID users, please follow the below steps.

Run ldapsearch to extract the names of all users.

ldapsearch -x -h oidserver.corp.company.com -p 389 -D cn=orcladmin -w passwd -L -b "cn=users,dc=corp,dc=company,dc=com" -s one "objectclass=*" dn > current_users.txt

From the file that is generated, Delete the text dn: (Use find - replace to do this). Also make sure that every entry is in one single line.

Run the ldapdelete to delete all the users from the file.

ldapdelete -x -h oidserver.corp.company.com -p 389 -D cn=orcladmin -w passwd -c -v -f current_users.txt

Login to oidadmin to confirm the delete.

Run the same for cn=Groups to delete all groups.

Migrate or copy users from one OID to another

When you set up a OID environment, you would want to copy or migrate the users from existing environment to the new environment.

Below steps will guide you on how to do it. (These commands are for Linux)

On the source OID
Set the $oracle_home appropriately. Example is below
$export ORACLE_HOME=/oracle/db/product/oid/

Go to $ORACLE_HOME/ldap/bin FOLDER
$cd $ORACLE_HOME/ldap/bin

Run the following command to export the users
$ldapsearch -x -h oidserver.corp.company.com -p 389 -D cn=orcladmin -w password -L -b "cn=users,dc=oidserver,dc=corp,dc=company,dc=com" -s one "objectclass=*" dn o cn gcpcompanycode givenname mail objectclass oimuserkey preferredlanguage sn telephonenumber userpassword > oid_filteruser.txt

Run the following command to export the groups
$ldapsearch -x -h oidserver.corp.company.com -p 389 -D cn=orcladmin -w password -L -b "cn=Groups,dc=oidserver,dc=corp,dc=company,dc=com" -s one "objectclass=*" > oid_filtergroup.txt

Copy the files generated (in this case oid_filteruser.txt and oid_filtergroup.txt) to the destination OID
$scp oid_filteruser.txt oid_filtergroup.txt otherOidServer.corp.company.com:/oracle/db/oid_files/.


On the destination OID
If this is a existing environment, then delete the existing users and groups before you import new users. To know how to delete the users, follow this link Delete Users in OID

Stop OID

Set the $oracle_home as follows
$export ORACLE_HOME=/oracle/db/product/oid/

Go to $ORACLE_HOME/ldap/bin FOLDER
$cd $ORACLE_HOME/ldap/bin

Then run the following commands one after the other. (DEVOID is the schema name of OID)
./bulkload connect="DEVOID" generate=true load=true file="/oracle/db/oid_files/oid_filteruser.txt"

Enter the password when prompted. Import will them complete in few seconds.

./bulkload connect="DEVOID" generate=true load=true file="/oracle/db/oid_files/oid_filtergroup.txt"

Enter the password when prompted. Import will them complete in few seconds.

Start OID

Go to oidadmin console and verify.

Unlock users in OID

There is always a need to unlock the user in OID. This can be done from the Konsole.

We must ideally create a file to do this so that we can use this multiple times.

Below are the steps.
  1. Create a file, say name it as unlockusers.sh.
  2. Paste the below content into the file.
    ldapmodify -p 389 -h servername.corp.company.com -D cn=orcladmin -w password -x -v <<EOF
    dn: cn=username, cn=Users,dc=corp,dc=company,dc=com
    changetype: modify
    add: orclpwdaccountunlock
    orclpwdaccountunlock: 1
    EOF
  3. Save and close the file.
  4. Give execute permission on that new file
    chmod +x unlockuser.sh
  5. Execute the file like
    ./unlockusers.sh

Next time on, all you need to do is change the username and execute the file.

Wednesday, June 9, 2010

WSIMPORT configuration in Maven

While developing a webservice client, we need to generate the client stub from the wsdl. There are many ways of doing this. One way is to use the Maven wsimport plugin.

Below is the way how we do it.

Use "mvn -P wsimport" generate a fresh JAX-WS client, then check that client
into subversion as source. Whenever the service contract changes, run mvn wsimport again. (Each time you
run it with the wsimport profile, maven will clean the source folder and regenerate all the JAX-WS client Javas)

Use the following link to learn how to make a Spring config for Spring-loading the JAX-WS client:
http://static.springsource.org/spring/docs/2.5.x/reference/remoting.html#remoting-web-services-jaxws-access

Note: if you don't specify the wsimport profile with the "mvn -P wsimport" command, then this module simply builds
a straight java jar. This nice selective build feature of maven lets us checkin the jaxws java artifacts to
subversion, and lets us control when we do new java generation only when the service interface changes.


<profiles>
<profile>
<id>wsimport</id>
<build>
<defaultGoal>install</defaultGoal>

<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-3</version>
<configuration>
<descriptorRefs>
<descriptorRef>
jar-with-dependencies
</descriptorRef>
</descriptorRefs>
<archiverConfig>
<duplicateBehavior>
skip
</duplicateBehavior>
</archiverConfig>
</configuration>
</plugin>

<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>clean</goal>
</goals>
<configuration>
<filesets>
<fileset>
<directory>
src/main/java/com/company/proj/serviceclient/module
</directory>
<includes>
<include>
**/*.java
</include>
<include>
**/*.properties
</include>
</includes>
<followSymlinks>
false
</followSymlinks>
</fileset>
</filesets>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>1.12</version>
<executions>

<execution>
<id>UserManagementClient</id>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<keep>true</keep>
<sourceDestDir>src/main/java</sourceDestDir>
<xdebug>true</xdebug>
<verbose>true</verbose>
<target>2.1</target>
<extension>true</extension>
<bindingFiles><bindingFile>${basedir}/src/main/resources/generateElementProperty.binding</bindingFile></bindingFiles>
<!-- <xauthFile>${basedir}/src/main/resources/authFile</xauthFile> -->
<wsdlUrls>
<wsdlUrl>
http://server.companyname.com:8001/projectcontext/1.0.0?wsdl
</wsdlUrl>
</wsdlUrls>
<packageName>
com.equinix.gse.serviceclient.usermanagement
</packageName>
</configuration>
</execution>
</executions>


<!-- if you want to use a specific version of JAX-WS, you can do so like this -->
<!--dependencies>
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-tools</artifactId>
<version>2.1.7</version>
</dependency>
</dependencies-->
</plugin>

</plugins>

</build>
</profile>
</profiles>

Tuesday, June 8, 2010

Transaction Management using Spring

Spring provides a comprehensive transaction support. And if you are using spring, you must be using transaction management that comes with it. It provides a good set of abstractions for transaction management.

You can implement transaction management with a few configurations in the application context file of spring and no additions or alterations to the java code.

Below is the configuration which is required for single Database transaction management.

<!-- ***** Transaction Manager ****** -->
<bean id="txManager1"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="projectDataSource" />
</bean>
<!-- ****** Transaction Definitions ***** -->
<!-- Default Isolation level is used - READ COMMITTED -->

<tx:advice id="txAdvice1" transaction-manager="txManager1">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>

<aop:config>
<aop:pointcut id="allProcessOperations"
expression="execution(* com.company.proj.bo.process.*Process.*(..))" />
<aop:advisor advice-ref="txAdvice1"
pointcut-ref="allProcessOperations" />
</aop:config>

The projectDataSource is ofcource the datasource bean which you must define for your datasource.

The above configuration binds all the operations on the projectDataSource into one transaction.
The AOP pointcut "execution(* com.company.proj.bo.process.*Process.*(..))" indicates that all the methods under all the classes ending with "Process" under the package com.company.proj.bo.process will be considered in transaction management.

The TX and AOP schema locations are
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

Any exception during the execution of a method which is bound under the above transaction will automatically rollback all changes. If the method completes without any exceptions, then the changes will be committed.

Distributed Transaction management
If you have distributed transactions in your method, then we can bind that method under JTA transaction

You may have a scenario where you are altering two data sources and also publishing into a JMS queue. All these operations can be bound under a JTA transaction. The configuration is as below.

<!-- ========== TX MANAGER ============= -->
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="javax.transaction.TransactionManager"/>
</bean>

<tx:advice id="txAdviceJTA" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="persistData*" propagation="REQUIRED" timeout="120000"/>
</tx:attributes>
</tx:advice>

<aop:config>
<aop:pointcut id="processOperations"
expression="execution(* com.company.proj.bo.process.MyProcess.*(..))" />
<aop:advisor advice-ref="txAdviceJTA"
pointcut-ref="processOperations" />
</aop:config>

Note that if a datasource or a JMS connection factory must be used in a JTA transaction, then they must be XA enabled. Otherwise they will not be involved in a JTA transaction.

Send Text Message To JMS Queue - Spring

Since I am working on Spring these days, I would post more on Spring as I have realised that Spring is the most comprehansive and more developer friendly framework among all the available frameworks in Java programming language.

Below is a class (the full code infact) that is useful to publish a text mesage into a JMS queue. Note that it use the Spring JmsTemplate. The configuration of which is given after the code snippet.


import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

/**
* Class to send JMS through spring jms template
*
* @author Darel
*
*/
public class JMSSender {
private JmsTemplate jmsTemplate;

public JmsTemplate getJmsTemplate() {
return jmsTemplate;
}

public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}

/**
* send JMS to JMS server
*
* @param queueName
* JMS queue name
* @param msg
* Queue object to be sent
*/

public void sendMesage(String queueName, final String msg) {
jmsTemplate.send(queueName, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {

return session.createTextMessage(msg);

}
});
}

}


Since this now a JMS client, we need the configuration in the application context file of Spring. The configuration is as below.


<!-- ************* JMS Client configuration ************************* -->
<bean id="jmsSender" class="com.mycompany.proj.service.util.JMSSender">
<property name="jmsTemplate">
<ref bean="queueTemplate" />
</property>
</bean>
<bean id="queueTemplate"
class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref bean="queueConnectionFactory" />
</property>
<property name="destinationResolver">
<ref bean="jmsDestinationResolver" />
</property>


</bean>
<bean id="queueConnectionFactory"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="permissionJndiTemplate" />
</property>
<property name="jndiName">
<value>${jms.connectionFactory}</value>
</property>
</bean>
<bean id="jmsDestinationResolver"
class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate">
<ref bean="permissionJndiTemplate" />
</property>
<property name="cache">
<value>true</value>
</property>
</bean>
<bean id="permissionJndiTemplate"
class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">
weblogic.jndi.WLInitialContextFactory
</prop>
<prop key="java.naming.provider.url">
${jms.provider.url}
</prop>
<prop key="java.naming.security.authentication">
${jms.authentication.type}
</prop>
<prop key="java.naming.security.principal">
${jms.security.principal}
</prop>
<prop key="java.naming.security.credentials">
${jms.security.credentials}
</prop>
</props>
</property>
</bean>


The values have $(...) which means that the value is got from the properties file. You can also hardcode the values if you do not have a properties file.

The above should be enough to publish a text message to the JMS queue. If you would need to publish a object. You can use the createObjectMessage method instead of createTextMessage.

You may also publidh a SOAP message into the JMS queue using this client. You will have to write the soap message object to a out stream and convert that to a String. The example is shown below.

//Here I am assuming that you have a method to create a SOAP message
SOAPMessage soapMessage = getSoapMessage();

ByteArrayOutputStream out = new ByteArrayOutputStream();

soapMessage.writeTo(out);

jmsSender.sendMesage(queueName, out.toString());

Extract Struct Object from pl/sql output - Spring

In most of our application where a procedure is written, most often than not we would have to extract the response of the oracle pl/sql call from its out parameters. Below is a small code snippet which can guide you to get that data which you need. There can be small changes depending on the jdbc framework you use. I have copied it from my project code which I had written using Spring JDBC and Oracle.

For Spring JDBC developers, the first 3 lines show how we can execute and extract the out object. The remaining lines of code is common for any framework.

Map outputMap = simpleJdbcCallObject.execute(map);

String result = (String) outputMap.get("O_RETURN_STATUS");

java.sql.Struct permissionStatus = (java.sql.Struct) outputMap
.get("P_RECORD_STATUS_OBJ");

Now that we have the Struct, let us see a scenario where we have a table object which contains a array of oracle objects. This table object is wrapped inside a wrapper object. (It is better to wrap the table inside a wrapper object which will be recieved as a Struct rather than getting the table object directly from the procedure call)

List recordStatusResult = new ArrayList();
try {
//Get the attributes from the wrapper object (Struct). We may have more than one table/elements inside the wrapper object. but in this case, we have only one table object
Object[] tableAttributeArray = permissionStatus.getAttributes();
//Make sure the the wrapper object is not null or empty
if (tableAttributeArray == null or tableAttributeArray.length < 1
or tableAttributeArray[0] == null) {

throw new Exception(
"No table data found in the response from the pl/sql procedure");
}
//Get the table object from the attributes, which is of type oracle.sql.ARRAY
ARRAY tableAttribute = (ARRAY) tableAttributeArray[0];
//Get the records from the table. Each record will be a object which is required for us.
Object[] structArray = (Object[]) tableAttribute.getArray();
//Make sure the table has atleast one record. You can skip this if not required to check
if (structArray == null or structArray.length < 1) {

throw new Exception(
"No Object data found in the response from the pl/sql procedure");
}
//Loop throw all the records to get the data.
Object struct;
for (int i = 0; i < structArray.length; i++) {
//Get the ith record from the table
struct = structArray[i];
//Each record will have one or more elements or properties
Object[] permissionData = ((Struct) struct).getAttributes();
//In my case, I store it in a list, you can extract the value like String s = (String)permissionData[0];
recordStatusResult.add(permissionData);
}
} catch (SQLException e) {
throw new Exception(
"Error while fetching the data from the pl/sql output.",
e);
}

The code above has comments which explain each step, so I believe no more explanation is required.
I need to return the data in a list, hence I am storing each object array record in the list.

Wednesday, April 21, 2010

Java Split String

Java has a useful method to slip the string into a string array based on the delimiter. Its the Split() method.

But most of the time we may use it incorrectly. One example is, if we have a string with comma separated values, Split can be used to split the comma separated values into String[]. But if we use this directly, most of us might have noticed that it does not consider the last trailing string.

ie., if the string is String str = "a,b,c,d,";
When we do String[] strArray = str.split(","); we get the string array with 4 values only. And not with 5 values. To get the complete string array, we must use as below;
String[] strArray = str.split(",", -1);

This is generally useful when you have multiple rows of such comma separated string or the string is dynamically created.

Tuesday, February 16, 2010

Java IDE

Java developers have a good advantage over developers using other programming languages. This is on the IDE. For Java, there is a good choice of quality IDE's available.

The top ones are IntelliJ IDEA, Eclipse and NetBeans. There are a few more like JBuilder, JCreator and the one from Oracle, which is JDeveloper.

The first three are of course widely used and has a big community. Out of these, IntelliJ IDEA is not free, but the other two are. Eclipse and NetBeans are open source projects and are freely available.

I have some experience in all these three IDE's and would like to put down what I think about them.

IntelliJ is the best Java IDE I have seen. It has all the java developer needs, which includes easy configuration, loads of features, good usability. But since it is not free, only few companies consider it in their budget and most companies cannot afford it. But if you can afford it, you will enjoy developing using this IDE.

Then we come down to Eclipse and NetBeans. If we would be discussing a few years back, Eclipse would be clearly a better choice, since NetBeans was not that great. But since NetBeans 6+ was released by Sun, I feel Netbeans has over taken Eclipse in usability and ease of use.

I have used both Eclipse 3.5 and NetBeans 6.7 recently and I was with ease with NetBeans and Eclipse was a head ache while configuration. Eclipse has of course a lot more plugins and some additional features when compared to NetBeans. But, setting up a project and starting to use is much easier in NetBeans. The features available were enough as per my requirement and I did not find a need for more.
Speed wise, I felt Eclipse was faster, as NetBeans takes a long time in scanning through all packages.

If you ask my opinion, I would select NetBeans as configuration has been my weakness and I am worst in that and I get frustrated doing it. NetBeans also comes with a good profiler which is very useful. On other features, there is not much of a difference between Eclipse and NetBeans.
I would say the future for NetBeans looks better than Eclipse. Then again, if you have been using Eclipse for a long time, you should prefer Eclipse.

Wednesday, January 13, 2010

My mistake

Today a strange thing happened while I was working on our company project. We use Sun webserver to deploy our java application.

We were testing our application as its that scary testing phase. (I say scary because, we have a points system where our points are directly related to the number of bugs found while testing.)

And on such a day, our application which till afternoon was working fine, suddenly stopped working. It could not connect to the database!

I checked everything, the code, the connection pool classes, the web server configuration, the data source settings and configuration and even the database.
I and my team broke our heads to resolve the issue. But all was going in vain.

Then after an hour and half, I finally decided to blame it on the database and told the same to the DBA. For which he ofcourse disagreed.

Then the matter was escalated and our development head for help. By looking the at logs he that the .dtd is missing.
Well, there were only 2 xml files, one is web.xml and other is sun-web.xml (sun-web.xml is specific to Sun wevserver). Both were pointing to a internet site of Sun (Example : http://www.sun.com/software/dtd/appserver/sun-web-app_2_5-0.dtd).

I decided to check them on the browser and to my surprise, I found that the Sun's server which hosts these .dtd files has gone down.

Phew, finally found the issue , We then downloaded the .dtd file from some other place and placed it in the config folder of the sun webserver.
All was fine then, the application started working fine.

But due to this lack of knowledge, we wasted about 2 hours, which can be crucial.

So the moral of the story is that any server can go down, so always make sure you place the .dtd or .xsd file which you are referring in your xml on your local server.

Tuesday, January 12, 2010

Avoid namespace in Axis2

To avoid a namespace in the web service request in Axis2, you can use the following trick.

This will not work if you want to deploy multiple services or endpoints within the same code (services.xml).
But if you have one service and the services.xml of Axis2 is dedicated for it, then you can achieve the option of not sending /setting the namespace from the client.

For this, simply remove the serviceGroup tag from services.xml and keep only one service in the services.xml file.

Example : If your services.xml file is
<?xml version="1.0" encoding="UTF-8"?>
<serviceGroup>
<service name="MainService" scope="application">
<description>
MainService Service
</description>
<operation name="processSOAPRequest">
<messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
</operation>
<parameter name="ServiceClass">com.darel.server.service.MainService</parameter>
</service>
</serviceGroup>

Change it by removing the <serviceGroup> and put the service as the main element.
<?xml version="1.0" encoding="UTF-8"?>
<service name="MainService" scope="application">
<description>
MainService Service
</description>
<operation name="processSOAPRequest">
<messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
</operation>
<parameter name="ServiceClass">com.darel.server.service.MainService</parameter>
</service>

Since there is only one service, Axis2 does not make the namespace mandatory in the Soap request.

Soap Client with XML DOM

Below is a sample soap client, which can take in a XML DOM, which is got from a xml string.

String targetERP = "http://myserver.com/NewWebService/services/ServiceName";

SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance();
connection = (SOAPConnection)scf.createConnection();

// SOAPFactory sf = SOAPFactory.newInstance();

// Create the message
MessageFactory mf = MessageFactory.newInstance();
SOAPMessage message = mf.createMessage();

SOAPPart soapPart = ((SOAPMessage) message).getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
// message body
SOAPBody body = envelope.getBody();

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();

//strRequestXML is a XML string which may be generated by java.
ByteArrayInputStream x = new ByteArrayInputStream(strRequestXML.getBytes());
Document doc = db.parse(x);
body.addDocument(doc); // add the xml to the soap messahe body

((SOAPMessage) message).writeTo(System.out);
System.out.println("\n");
URL endpoint = new URL(targetERP);

SOAPMessage response = connection.call(message, endpoint);
// SOAPMessage response = connection.call("",
// endpoint);
connection.close();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
response.writeTo(baos);
responseStr = baos.toString();

Of course the imports are
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

import javax.xml.soap.*;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;

Monday, January 4, 2010

String builder using variable args

In many cases, we may have to append large number of strings to get a complete string which is desired by the program. One example can be the SQL string where you are appending the values to a sql string in java.

When it comes to appending large amount of strings, it better to use StringBuffer or StringBuilder (StringBuilder is faster since its not synchronized).
Appending to StringBuilder using .append can increase the amount of code and if done in single line can look ugly.

To avoid this, you can use the below method which does it in a clean way by calling a method and passing all string objects as variables.

/**
* Given a continuous string variables, it appends them using a string builder and returns a string.
*
* @param strings - Variable args, a unlimited variables of type String
* @return - A string which is built from the given string variables.
*/
public static String buildString(String... strings) {

    StringBuilder sb = new StringBuilder();

    for (String str : strings) {
        sb.append(str);
    }
    return sb.toString();
}

//Some method to call the above method by passing variable args
public void someMethod () {
    String str = buildString("This", " is", " a", " long string", " which will", " be ", " appended", " to demonstrate", " variable", " args", " feature");
}