axis2 Web service. Where to put my own configuration - java

I have written a Web Service in Java using axis2 and the POJO deployment (to a Tomcat server). My service opens a connection to a MySQL database. To do that, I need the connection string. Where do I put the connection string, so I don't have to hard code it into the code? And how do I access it from code? I would like to set this parameter somewhere on the service level, not globally for the whole server. Is this possible?

You could use tomcat to configure the DB connectivity for you and then just look up the javax.sql.DataSource using JNDI.
Have look at these for tomcat:
JNDI resources
JNDI datasource example
Using JNDI would also mean that you automatically become a little more compatible in case you ever need to move to a different web container/app server.

If you want to use a config file, you can place one at the following location:
axis2/WEB-INF/services/classes/config-file.xml
You can access this file in code using the AxisService classloader, which is available during the startUp(ConfigurationContext configctx, AxisService service) method. startUp() is fired when your service is started (either post-deployment or after a container restart).
import org.apache.axis2.engine.ServiceLifeCycle;
public class LifeCycleImpl implements ServiceLifeCycle {
public void startUp(ConfigurationContext configctx, AxisService service) {
InputStream in = service.getClassLoader().getResourceAsStream("config-file.xml");
//Extract your database config from the input stream
//Create database connection
//Store the connection as a service parameter using service.AddParameter
}
During the init(ServiceContext serviceContext) method of your service implementation class, you can get access the database connection created during ServiceLifeCycle.startUp() via the ServiceContext.getAxisService().getParamterValue() method.
Note: You must specify the ServiceLifeCycle implementation class in the your service's services.xml file, as the class attibute of the service tag:
<!-- The class attribute defines the hook into the Service lifecycle methods
startUp and shutDown -->
<service name="YourService" class="com.macima.webservice.LifeCycleImpl">
<!--Specify the web service's implementation class -->
<parameter name="ServiceClass">com.macima.webservice.ServiceImpl</parameter>
<!--Declare methods exposed by the web service-->
<operation name="getSomething">
<messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</operation>
</parameter>
</service>
With this approach, your config file is held outside of the aar file. The benefit is you can promote the same aar file through different test environments, picking up the relevant settings for each environment in the environment specific config file. Additionally you can edit the config file without having to open up the aar file.

Related

Configuring Wildfly standalone "<remote-naming/>"

Looking for examples of how to configure a Wildfly server to be very simple standalone JNDI namespace server.
I would like to specify value pairs so that our external java applications can access and use the defined resources using JNDI API's.
From the Documentation it is clear that I have to use the XML tag.
Remote JNDI Configuration
The Naming subsystem configuration may be
used to (de)activate the remote JNDI interface, which allows clients
to lookup entries present in a remote WildFly instance.
Only entries within the java:jboss/exported context are accessible
over remote JNDI. In the subsystem's XML configuration, remote JNDI
access bindings are configured through the XML
element:
<remote-naming />
But what isn't clear is HOW to use it, I cant find any examples anywhere.
If I had the following object:
String: MyFirstProperty
How do Insert this into the <remote-naming /> tag so that Wildfly makes it available for me to retrieve?

Get the CATALINA_BASE property from inside a Java Web Service

Dear fellow Developers,
I am working on improving my Java Web Services, and I am trying to use a more delicate way of getting the directory path of properties files in a Java Web Service.
In order to make my Java Web Application easier to be deployed on an Apache Tomcat Server, I add the following line to the web.xml file:
<env-entry>
<env-entry-name>loggerPropertyFile</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>/Some/Long/Directory/File/Path/Which/May/Change/conf/LoggerInfo.properties</env-entry-value>
</env-entry>
As the above xml code depicts, I have placed a Properties file somewhere in the local Filesystem, and I want my Web Service to initialize its logger class, based on that configuration. As you can realize this path changes every time I deploy my web service to another server.
Thus, I figured out that I may be able to use the $CATALINA_BASE property, in order to make the environment entry path smaller. How can I retrieve the CATALINA_BASE value from inside my Java Web Service's Code (how is done on Linux and how is done on Windows)??
Thank you.
try System.getProperty("catalina.base");

How to read external properties files in WebSphere?

I developed a sample web application which will read the data from an external properties file. The properties file is in the source folder in my system and is not included inside the WAR file.
The property file is accessed like this:
Properties prop = new Properties();
//File f1 = new File("Property.properties");
prop.load(getClass().getClassLoader().getResourceAsStream("Property.properties"));
How do I access this property file externally inside the WAR file?
What changes have to be made in the code to read it in the WAR file?
I think the most versatile approach is to define a simple environment entry as described in the section EE.5.4 Simple Environment Entries of Java™ Platform, Enterprise Edition (Java EE) Specification, v5.
From the section (page 68):
A simple environment entry is a configuration parameter used to
customize an application component’s business logic. The environment
entry values may be one of the following Java types: String,
Character, Byte, Short, Integer, Long, Boolean, Double, and Float.
You may also use URL connection factory as described in the section EE.5.6.1.4 Standard Resource Manager Connection Factory Types of the specification.
The Application Component Provider must use the java.net.URL resource
manager connection factory type for obtaining URL connections.
Both require a definition of a resource reference in the deployment descriptor WEB-INF/web.xml of your web application so you can inject the value using #Resource or use JNDI API with java:comp/env as the entry point.
The benefit is that you can change the configuration of your web application without having to recompile the code as well as let you change it using an application server's administrative tools your admins are accustomed with.
In web.xml you define the resource reference.
<resource-ref>
<res-ref-name>propertiesURL</res-ref-name>
<res-type>java.net.URL</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<resource-ref>
<res-ref-name>propertiesPath</res-ref-name>
<res-type>java.lang.String</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
Then in your code you use the following to access the values:
#Resource
String propertiesPath;
#Resource
URL propertiesURL;
With this you met the requirements of Java EE and you can use propertiesPath or propertiesURL as if they were passed as input parameters to your methods.
Now, it's time to meet expectations of WebSphere Application Server.
What you defined are logical names that need to be mapped to their administered names (an application server knows about and can provide to the application).
In WebSphere Application Server you use WebSphere Binding descriptor WEB-INF/ibm-web-bnd.xml with the following configuration:
<?xml version="1.0" encoding="UTF-8"?>
<web-bnd xmlns="http://websphere.ibm.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-bnd_1_1.xsd"
version="1.1">
<virtual-host name="default_host" />
<resource-ref name="propertyURL" binding-name="propertyURL" />
<resource-ref name="propertyURL" binding-name="propertyURL" />
</web-bnd>
When the application gets deployed WAS allows you to map these mappings to its administered resources. Use the ISC console to define values of the environment entries and map them to the application.
It has became easier with WebSphere Liberty Profile. I described the mechanism as offered by WLP in my article Using #Resource to access JNDI in WebSphere AS 8.5 Liberty Profile.
You have three options:
configure the Websphere to include the directory which contains the property file in the classpath. Don't know how to do it, but I'm sure it is possible, since our application does the same thing
include the property file in the war archive. You probably don't want to do that.
instead using the classloader to load the property file use the file api with an absolute path. I'm not completely sure WAS does allow that, but it is a bad idea anyway, because it makes your application very dependent on things that it really shouldn't care about, such as the installation path of your application.
WebSphere has two folders on the classpath, properties can be loaded from there:
Enterprise Applications > myear > Manage Modules > myjar.jar > Class loader viewer
4 - Extension - com.ibm.ws.bootstrap.ExtClassLoader
file:/projekte/IBM/WebSphere/AppServer-8.5/classes/
file:/projekte/IBM/WebSphere/AppServer-8.5/lib/

Java Web Services - Defining Server Location

I have one final hurdle to get over with the web services application I am working with; I need to be able to override the default settings used to set the schema location and soap address location in the generated WSDL file.
When I deploy the application (GlassFish v2.1 on Red Hat linux) it uses the local server name in the URLs but it needs to use the public domain name instead. I was able to save the WSDL file locally, change the URLs, make it public, generate a test application externally from the file, and lastly was able to successfully run a test.
I have now journeyed into the realm of JAX-WS custom bindings but I'm hoping that I either overlooked a simpler solution or the bindings are not as complicated as they look at first glance. The web service implementation is through a stateless EJB (e.g. MyWS.java below). The generated WSDL file would look like MyWSDL.wsdl (see below).
In the xsd:import tag I need to change schemaLocation to
http://test.mycompany.com/MyWSService/MyWS?xsd=1
instead of
http://local-server-name/MyWSService/MyWS?xsd=1
and in the soap:address tag I need to change location to be
http://test.mycompany.com/MyWSService/MyWS
instead of
http://local-server-name/MyWSService/MyWS.
MyWS.java
#WebService(name="MyWS",
portName="MyWSPort",
serviceName="MyWSService",
targetNamespace="http://test.mycompany.com/")
#Stateless()
public class MyWS {
#WebMethod(operationName="testLogin")
public String testLogin(#WebParam(name="username") String username,
#WebParam(name="password") String password) {
String retVal = "Test Failed.";
//do some stuff
return retVal;
}
...
}
MyWSDL.wsdl
<definitions targetNamespace="http://test.mycompany.com/" name="MyWSService">
<types>
<xsd:schema>
<xsd:import namespace="http://test.mycompany.com/" schemaLocation="http://local-server-name/MyWSService/MyWS?xsd=1"/>
</xsd:schema>
</types>
<service name="MyWSService">
<port name="MyWSPort" binding="tns:MyWSPortBinding">
<soap:address location="http://local-server-name/MyWSService/MyWS"/>
</port>
</service>
</definitions>
I was able to resolve the issue by changing the configuration of the GlassFish HTTP Service. I set the server's alias name to test.mycompany.com:80 for the HTTP listener being used for the web services application. Typically we have this kind of configuration in our web servers so initially I didn't even consider the application server configuration.
How are you generating the WSDL? Are you generating it by hand? Are you generating it using wsgen with the -wsdl option?
If you're deploying with JAX-WS you shouldn't actually have to do either of those things. Instead you should be able to go to...
<SERVER_URL>/<CONTEXT_LOCATION>/<SERVLET_URL>?wsdl
...and the JAX-WS servlet will automatically generate a wsdl on the fly with the correct location.

How can I store sensitive data in Java configuration files?

I have some code that I want to make public. The code sends email via servers, connects to databases, and other tasks requiring usernames/passwords.
I'd like to store the passwords and such in a seperate configuration file so that I don't have to sanitize my code on every commit.
How can I do this? It would be easy to do in C using #define, but I'm not sure how to accomplish this in Java.
EDIT: The environment I'm using is Glassfish
The basic method is put the information in a properties file and use the Properties class to load it at run time. If you're using a J2EE server, database connections are configured in the server and the code references them by an abstract name.
I think I should add that if you're using a server, how to configure it and how to get the connections to your code will vary by server and J2EE level so post your environment. Using the Properties class is pretty obvious just by looking at the javadoc and the load() methods.
In glassfish, go to the admin console and under Resources create a new connection pool. That defines your database connection and will share a pool of those connections among your applications. Now under JDBC Resources, create a new entry that maps that pool to a name. The name is usually something like jdbc/myappname.
For a J2EE5 or later application, you can now add this as a class level variable:
#Resource(mappedName="jdbc/myappname") DataSource myDS;
At runtime the server will inject that resource to your database pool. Then when you need a connection, you can do this inside any method:
Connection conn = myDS.getConnection();
The result is your code doesn't have to care at all about the database connection information or managing a pool of connections. You can deploy the identical code on development and production servers, and they will get an appropriate connection. In order to get the injection, it has to be a class the server creates like an EJB, servlet, tag library handler, or JSF managed bean.

Categories

Resources