Create SOAP Web Service (Java API for XML Web Service, JAX-WS) with Wildfly and Secure Web Service


SOAP Web Service is standard way to integrate your application with other applications. Wildfly is base on Java EE, so it is provide seamless platform to build SOAP Web Service on JAX-WS specification. Create SOAP web service is very simple, at least you need only just on one annotation to convert simple POJO to web service. you can follow step below steps to create web service. The server and client communicate with each other via XML over SOAP (Simple Object Access Protocol) message. A client sends XML SOAP message to server. After processing the request, server send back response to client via XML SOAP message. Request and response XML is defined by WDSL. On this post, I show how to create SOAP Web Service and secure the web service.

Create JAX-WS web service

First is to just create Dynamic Web Project by using eclipse.

Create Dynamic Web Project
select Run time environment
config folder
Finish
Create package, interface and implement class. First, I'll create package my package is com.jaxws.webservice
Create package
Click finish, then you need to create interface
Create Interface
Next is to import JPA project for import entity class and add EJB project to import business logic.
Import JPA Project
Import EJB Project
Finish
Finish import related project
Now, you should have JPA entity class and business logic. Next is to define interface code.

package com.jaxws.webservice;

import java.util.List;

import com.jpa.model.User;

public interface UserCrud {
public void save(User user);
public List<User> getUsers();
}
Then you can create class that implement UserCrud interface
package com.jaxws.webservice;

import java.util.List;

import javax.ejb.EJB;

import com.ejb.crud.UserEjb;
import com.jpa.model.User;

public class UserCrudImp implements UserCrud {
@EJB
private UserEjb userEjb;
@Override
public void save(User user) {
userEjb.save(user);
}

@Override
public List<User> getUsers() {
return userEjb.getUsers();
}

}
Now Convert your simple class to web service by add annotation to your interface and the interface implement class. First, we will add annotation to the interface.
package com.jaxws.webservice;

import java.util.List;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

import com.jpa.model.User;
@WebService(
name="userCrud",
targetNamespace="https://wildfly.itstikk.pro"
)
@SOAPBinding(style=Style.DOCUMENT)
public interface UserCrud {
@WebMethod(action="save",operationName="saveUser")
@WebResult(name="saveResult")
public void save(@WebParam(name="userParam") User user);
@WebMethod(action="get",operationName="getUser")
@WebResult(name="user")
public List<User> getUsers();
}

Next, you need to add annotation to the interface implement class.
package com.jaxws.webservice;

import java.util.List;

import javax.ejb.EJB;
import javax.jws.WebService;

import com.ejb.crud.UserEjb;
import com.jpa.model.User;
@WebService(
endpointInterface="com.web.service.UserCrud",
portName="userCrudPort",
serviceName="userCrudService"
)
public class UserCrudImp implements UserCrud {
@EJB
private UserEjb userEjb;
@Override
public void save(User user) {
userEjb.save(user);
}

@Override
public List<User> getUsers() {
return userEjb.getUsers();
}

}

If you set your document style as document, you need to add JAXB annotation to your JPA Entity Bean.
package com.jpa.model;

import java.io.Serializable;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;


/**
 * The persistent class for the usr01tbl database table.
 *
 */
@Entity @XmlRootElement(name="User") @XmlType(propOrder= {"id","firstname","lastname"})
@Table(name="usr01tbl")
@NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@SequenceGenerator(name="USR01TBL_ID_GENERATOR", sequenceName="USR01TBL_ID_SEQ")
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="USR01TBL_ID_GENERATOR")
private Integer id;
@Column(name="firstname")
private String firstname;
@Column(name="lastname")
private String lastname;

public User() {
}

@XmlElement
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}

@XmlElement(required=true)
public String getFirstname() {
return this.firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}

@XmlElement(required=true)
public String getLastname() {
return this.lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}

}

Next is to add your dynamic web project that includes SOAP web service to enterprise application project and deploy to Wildfly and check

Create Enterprise Application Project
Select Runtime Environment
Add Project to be deployed

Finish
After start server you could see the endpoint.
 address=http://localhost:8080/java-ee-02-jaxws/userCrudService
 implementor=com.jaxws.webservice.UserCrudImp
 serviceName={http://webservice.jaxws.com/}userCrudService
 portName={http://webservice.jaxws.com/}userCrudPort
 annotationWsdlLocation=null
 wsdlLocationOverride=null
 mtomEnabled=false
in your wildfly control portal you should see.
Wildfly control Portal
WSDL
you should be able to see wsdl as
http://localhost:8080/java-ee-02-jaxws/userCrudService?wsdl

Test JAX-WS web service.

Eclipse is a excellent tool to test soap web service. I will use web service explorer to test web service.

Open Web Service Explorer
This will link you to the browser and from browser you can use WSIL Page to  search for WSDL

Open WSDL Page

Input your WSDL
Next is to click go
Click Go
You can test each method by this portal.

Test getUsers

Secure Web Service

In general cases, you don't just publish your web service API and just let any one to access it. You need to identify and give access to certain person to access it, this is concerned to security issue. In order to secure web service, you must apply SSL and HTTPS for encrypting the communication between server and client. And you must apply service authentication to verity access person. Service authentication could be done by application level or container level since you don't want to create every authentication verification for every web services you created.

First you need to set up HTTPS for your Wildfly. You need to create key store. About how to create key store and set up HTTS you can refer here
$cd $JBOSS_HOME/standalone/configuration
$vi standalone.xml
and you just add as below
 <subsystem xmlns="urn:jboss:domain:webservices:2.0" statistics-enabled="true">
<modify-wsdl-address>true</modify-wsdl-address>
            <wsdl-host>${jboss.bind.address:127.0.0.1}</wsdl-host>
<wsdl-secure-port>8443</wsdl-secure-port>
<wsdl-uri-scheme>https</wsdl-uri-scheme>
            <endpoint-config name="Standard-Endpoint-Config"/>
            <endpoint-config name="Recording-Endpoint-Config">
                <pre-handler-chain name="recording-handlers" protocol-bindings="##SOAP11_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP ##SOAP12_HTTP_MTOM">
                    <handler name="RecordingHandler" class="org.jboss.ws.common.invocation.RecordingServerHandler"/>
                </pre-handler-chain>
            </endpoint-config>
            <client-config name="Standard-Client-Config"/>
        </subsystem>
        <subsystem xmlns="urn:jboss:domain:weld:3.0"/>
Now, restart your server and try to access your wsdl as below.
https://localhost:8443/java-ee-01-jaxws/userCrudService?wsdl

and you can see your wsld as

Output WSDL's xml
This is ensure that every communication between server and client is encrypted. Now your server - client communication is encrypted and secured. Next you need to create user and user's group (role-name) for user who you will allow to call the web service. This is regard as user identification or user authentication and authorization. Only user who has principal and credential is allowed to call and use the web service.

Create user and role

You can use add-user.sh to create user and role.
$cd $JBOSS_HOME/bin
$bash add-user.sh

What type of user do you wish to add?
 a) Management User (mgmt-users.properties)
 b) Application User (application-users.properties)
(a): b

Enter the details of the new user to add.
Using realm 'ApplicationRealm' as discovered from the existing property files.
Username : usr03
Password recommendations are listed below. To modify these restrictions edit the add-user.properties configuration file.
 - The password should be different from the username
 - The password should not be one of the following restricted values {root, admin, administrator}
 - The password should contain at least 8 characters, 1 alphabetic character(s), 1 digit(s), 1 non-alphanumeric symbol(s)
Password :
Re-enter Password :
What groups do you want this user to belong to? (Please enter a comma separated list, or leave blank for none)[  ]: webservice
About to add user 'usr03' for realm 'ApplicationRealm'
Is this correct yes/no? yes
Added user 'usr03' to file 'D:\Devs\wildfly-10.1.0.Final\standalone\configuration\application-users.properties'
Added user 'usr03' to file 'D:\Devs\wildfly-10.1.0.Final\domain\configuration\application-users.properties'
Added user 'usr03' with groups webservice to file 'D:\Devs\wildfly-10.1.0.Final\standalone\configuration\application-roles.properties'
Added user 'usr03' with groups webservice to file 'D:\Devs\wildfly-10.1.0.Final\domain\configuration\application-roles.properties'
Is this new user going to be used for one AS process to connect to another AS process?
e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls.
yes/no? yes
To represent the user add the following to the server-identities definition <secret value="UWY0OGQ4dXYxMiFA" />
Press any key to continue . . .
Here I have create usr03 belong to group webservice. Next is to manage user from management console.
create Group (webservice)
Next is to create user (usr03) on the management console.
create user (usr03) belong to webserivce group
After you create user and group, you need to add annotation to your web service interface. You need to add @RolesAllowed({"webservice"}).
package com.web.service;

import java.util.List;

import javax.annotation.security.RolesAllowed;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

import com.jpa.model.User;
@RolesAllowed({"webservice"})
@WebService(
name="userCrud",
targetNamespace="https://wildfly.itstikk.pro"
)
@SOAPBinding(style=Style.RPC)
public interface UserCrud {
@WebMethod(action="save",operationName="saveUser")
@WebResult(name="saveResult")
public void save(@WebParam(name="userParam") User user);
@WebMethod(action="get",operationName="getUser")
@WebResult(name="user")
public List<User> getUsers();
}

Edit /WEB-INF/web.xml as below
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>java-ee-02-jaxws</display-name>
  <security-constraint> 
    <web-resource-collection> 
      <web-resource-name>webservice auth</web-resource-name> 
      <url-pattern>/*</url-pattern>
     <!-- <http-method>POST</http-method> -->
    </web-resource-collection> 
    <auth-constraint> 
      <role-name>webservice</role-name> 
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint> 
  </security-constraint> 
  <login-config> 
    <auth-method>BASIC</auth-method>
    <realm-name>ApplicationRealm</realm-name> 
  </login-config> 
  <security-role> 
    <role-name>webservice</role-name> 
  </security-role>
</web-app>

Then create jboss-web.xml and put as below.
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>  
  <context-root>java-ee-02-jaxws</context-root>  
  <security-domain>java:/jaas/other</security-domain>
</jboss-web>
Now your configuration file should be like below.
Configuration files
Finally, restart Wildfly Server. To test your web service with HTTPS and BASIC Authentication you just use your browser. Your browser should show authentication dialog.
authentication dialog
WDSL output

To test your webservice you can use SoapUI and use auth to create request.
Use SoapUI to test secure web service with authentication

Reference



No comments:

Post a Comment

Feature Recently

Running Wildfly Application Server in Domain Mode

  Wildfly application server provides two modes of how to run application one wildfly application server. It is very simple if you run your ...

Most Views