I have been busy with the project, and the update is a bit late. Today, I will take the time to talk about publishing services through cxf under osgi. For details, please refer to the osgi-http component.
http://git.oschina.net/wyuxiao729/osmp/tree/master/osmp-http?dir=1&filepath=osmp-http&oid=c57f2e1633345a9298a42656cf707505f88edf1e&sha=e09ee23dba8ee3ef0239747604f6f1179eae0168
In fact, it is very simple to use the cxf publishing service in the osgi environment. cxf has encapsulated the release of native ws services such as jaxws and jaxrs, and it is relatively simple to implement. It is OK to define the interface and publish the implementation. In this example of osgi-http, two methods are published through cxf: restful and ws services.
Defining the interface is very simple, the code is as follows:
Interface definition:
/* * Project: OSMP * FileName: IRestPlatformTransport.java * version: V1.0 */ package com.osmp.http.transport; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Response; /** * Description: Unified service interface REST * @author: wangkaiping *@date: Aug 9, 2016 9:14:42AM 10:51:30AM */ public interface IRestPlatformTransport { /** * retrieve data * @param source source json format {from:xx} * @param interfaceName interface name, corresponding service * @param parameter interface parameter, corresponding to service parameter * @return */ public Response data(String source,String interfaceName,String parameter,HttpServletRequest request); /** * retrieve data * @param source source json format {from:xx} * @param interfaceName interface name, corresponding service * @param parameter interface parameter, corresponding to service parameter * @return */ public Response dataPost(String source,String interfaceName,String parameter,HttpServletRequest request); /** * Submit task * @param source source json format {from:xx} * @param interfaceName interface name, corresponding service * @param parameter interface parameter, corresponding to service parameter * @return */ public Response task(String source,String interfaceName,String parameter); }
Interface implementation:
/* * Project: OSMP * FileName: RestPlatformTransport.java * version: V1.0 */ package com.osmp.http.transport; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import com.osmp.http.define.ResponseBody; import com.osmp.http.define.RtCodeConst; import com.osmp.http.service.DataServiceProxy; import com.osmp.http.service.ServiceFactoryManager; import com.osmp.http.tool.ExceptionHandleProvider; import com.osmp.intf.define.config.FrameConst; import com.osmp.intf.define.model.InvocationDefine; import com.osmp.intf.define.model.ServiceContext; import com.osmp.utils.base.JSONUtils; import com.osmp.utils.net.RequestInfoHelper; /** * * Description: Unified service interface REST * @author: wangkaiping *@date: Aug 9, 2016 9:16:20AM 10:51:30AM */ public class RestPlatformTransport implements IRestPlatformTransport, InitializingBean { private Logger logger = LoggerFactory.getLogger (RestPlatformTransport.class); @POST @Path(value = "/{svcName}") @Produces(MediaType.APPLICATION_JSON) public Response dataPost(@FormParam(FrameConst.SOURCE_NAME) String source, @PathParam("svcName") String interfaceName, @FormParam(FrameConst.PARAMETER_NAME) String parameter, @Context HttpServletRequest request) { return data(source, interfaceName, parameter, request); } @GET @Path(value = "/{svcName}") @Produces(MediaType.APPLICATION_JSON) public Response data(@QueryParam(FrameConst.SOURCE_NAME) String source, @PathParam("svcName") String interfaceName, @QueryParam(FrameConst.PARAMETER_NAME) String parameter, @Context HttpServletRequest request) { return Response.ok().entity("ok") .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); } @GET @Path(value = "/task") @Produces(MediaType.APPLICATION_JSON) public Response task(String source, String interfaceName, String parameter) { return null; } }
Here we use the jsr annotation to define the interface request type, the interface request url and the mediaType type in the interface
Annotation in the code
@POST defines the type of request
@Path(value="/{svcName}") restful style request path
Of course, annotations can also be written on the interface!
Because here is only to explain the release of the restful interface. I have removed the specific implementation of the method. If you are interested, you can take a look at the code in osmp-http.
Next webservice interface:
/* * Project: OSMP * FileName: ISoapPlatformTransport.java * version: V1.0 */ package com.osmp.http.transport; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebService; import com.osmp.http.define.ResponseBody; import com.osmp.intf.define.config.FrameConst; /** * Description: Unified service interface soap * @author: wangkaiping *@date: Aug 9, 2016 9:15:42AM 10:51:30AM */ @WebService(targetNamespace = "osmp.soap") public interface ISoapPlatformTransport { @WebMethod(action = "data", operationName = "data") public ResponseBody data(@WebParam(name=FrameConst.SOURCE_NAME) String source, @WebParam(name=FrameConst.SERVICE_NAME) String interfaceName, @WebParam(name=FrameConst.PARAMETER_NAME) String parameter); }
The interface uses the jdk native jws annotation to define the namespace and method action and operationName and parameters of the interface. For details, please refer to the related information of jws and soap protocols.
webservice interface implementation:
/* * Project: OSMP * FileName: SoapPlatformTransport.java * version: V1.0 */ package com.osmp.http.transport; import java.util.Map; import javax.jws.WebService; import javax.servlet.http.HttpServletRequest; import org.apache.cxf.message.Message; import org.apache.cxf.phase.PhaseInterceptorChain; import org.apache.cxf.transport.http.AbstractHTTPDestination; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import com.osmp.http.define.ResponseBody; import com.osmp.http.define.RtCodeConst; import com.osmp.http.service.DataServiceProxy; import com.osmp.http.service.ServiceFactoryManager; import com.osmp.intf.define.config.FrameConst; import com.osmp.intf.define.model.InvocationDefine; import com.osmp.intf.define.model.ServiceContext; import com.osmp.utils.base.JSONUtils; import com.osmp.utils.net.RequestInfoHelper; /** * * Description: Unified service interface SOAP * @author: wangkaiping * @date: Aug 9, 2016 9:17:10AM 10:51:30AM */ @WebService(portName="port",serviceName="data",endpointInterface = "com.osmp.http.transport.ISoapPlatformTransport") public class SoapPlatformTransport implements ISoapPlatformTransport,InitializingBean{ private Logger logger = LoggerFactory.getLogger (RestPlatformTransport.class); private ServiceFactoryManager serviceFactoryManager; public void afterPropertiesSet() throws Exception { Assert.notNull(serviceFactoryManager,"PlatformServiceTransport property dataServiceManager not set.."); } public void setServiceFactoryManager(ServiceFactoryManager serviceFactoryManager) { this.serviceFactoryManager = serviceFactoryManager; } public ResponseBody data(String source, String interfaceName, String parameter) { Message message = PhaseInterceptorChain.getCurrentMessage(); HttpServletRequest request = (HttpServletRequest)message.get(AbstractHTTPDestination.HTTP_REQUEST); String ip = RequestInfoHelper.getRemoteIp(request); System.out.println("requstId:"+request.getAttribute(FrameConst.CLIENT_REQ_ID)); System.out.println("ip:"+ip); ResponseBody res = new ResponseBody(); // Get the corresponding service InvocationDefine define = serviceFactoryManager.getInvocationDefine(interfaceName); if (define == null) { res.setCode(RtCodeConst.ERR_CODE); res.setMessage("Service not found"); logger.warn("Service not found..."); return res; } // interface parameter validation Map<String, String> sourceMap = JSONUtils.jsonString2Map(source); if (sourceMap == null || sourceMap.get(FrameConst.CLIENT_FROM) == null) { res.setCode(RtCodeConst.ERR_CODE); res.setMessage("The interface parameter is illegal"); logger.warn("The interface parameter is illegal..."); return res; } sourceMap.put(FrameConst.CLIENT_IP, ip); // call the service ServiceContext serviceContext = new ServiceContext(sourceMap, interfaceName, parameter); DataServiceProxy serviceProxy = new DataServiceProxy(define, serviceContext); Object result = serviceProxy.execute(); res.setCode(RtCodeConst.SUCC_CODE); res.setData(result); return res; } }
After completing the interface definition and implementation. We can expose this interface as a service for external calls through cxf.
You can use the spring method or the buleprint method. Here I use spring way for compatibility. The configuration file is as follows:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:cxf="http://cxf.apache.org/core" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd"> <cxf:bus> <cxf:inInterceptors> <ref bean="requestParser"/> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean> </cxf:inInterceptors> <cxf:outInterceptors> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean> </cxf:outInterceptors> </cxf:bus> <bean id="webserver" class="com.osmp.http.transport.RestPlatformTransport"> </bean> <bean id="soapServer" class="com.osmp.http.transport.SoapPlatformTransport"> </bean> <bean id="objectMapper" class="com.osmp.http.tool.DefaultObjectMapper"></bean> <jaxrs:server id="restServiceContainer" address="/service"> <jaxrs:serviceBeans> <ref bean="webserver" /> </jaxrs:serviceBeans> <jaxrs:providers> <bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"> <constructor-arg index="0" ref="objectMapper"></constructor-arg> </bean> </jaxrs:providers> <jaxrs:extensionMappings> <entry key="json" value="application/json" /> </jaxrs:extensionMappings> <jaxrs:languageMappings> <entry key="en" value="en-gb" /> </jaxrs:languageMappings> </jaxrs:server> <jaxws:server id="soapServiceContainer" address="/soap"> <jaxws:serviceBean> <ref bean="soapServer" /> </jaxws:serviceBean> </jaxws:server> </beans>
So far, the code part is complete. If it is a traditional j2ee project. It can be accessed directly through http://ip:port/cxf.
So how do we publish in the osgi environment? It's actually very simple here. I use servicemix as the container. It has already integrated cxf, we can directly deploy it as a bundle. If it is karaf or native felix, it will be more troublesome. You need to install the dependency support of cxf-bundle first. I will not explain it here. Research!
Here the jar package that pom needs to depend on is
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-bundle</artifactId> </dependency> <dependency> <groupId>org.springframework.osgi</groupId> <artifactId>spring-osgi-core</artifactId> </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.core</artifactId> </dependency>
Building bundles with the maven plugin requires the use of the maven-bundle-plgin plugin, where we can define settings such as importing, exporting packages, and bundle-embedded jar packages. For detailed settings, see:
http://felix.apache.org/documentation/subprojects/apache-felix-maven-bundle-plugin-bnd.html
complete pom.xml
<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> <parent> <groupId>com.osmp.baseweb</groupId> <artifactId>osmp-parent</artifactId> <version>1.0.0</version> </parent> <artifactId>osmp-http</artifactId> <packaging>bundle</packaging> <name>osmp-http</name> <properties> <maven.test.skip>true</maven.test.skip> </properties> <build> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <extensions>true</extensions> <configuration> <instructions> <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName> <DynamicImport-Package>*;resolution:=optional</DynamicImport-Package> <Import-Package>com.osmp.intf.define.config, com.osmp.intf.define.interceptor, com.osmp.intf.define.model, com.osmp.intf.define.factory, com.osmp.intf.define.service, com.osmp.utils.net, com.osmp.utils.base</Import-Package> <Embed-Dependency>jackson-jaxrs,jackson-xc</Embed-Dependency> </instructions> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>com.osmp.baseweb</groupId> <artifactId>osmp-intf-define</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>com.osmp.baseweb</groupId> <artifactId>osmp-resource</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>com.osmp.baseweb</groupId> <artifactId>osmp-tools</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>com.osmp.baseweb</groupId> <artifactId>osmp-utils</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>com.osmp.baseweb</groupId> <artifactId>osmp-log</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.osgi</groupId> <artifactId>spring-osgi-core</artifactId> </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.core</artifactId> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-jaxrs</artifactId> <version>1.9.13</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-xc</artifactId> <version>1.9.13</version> </dependency> </dependencies> </project>
The typed jar package is of bundle type. Can run in osgi environment.
Visit in the servicemix environment: http://ip:8181/cxf You can see the restful interface and soap interface we have defined
The default access root path of cxf is cxf, which can be modified through servicemix configuration
I'm about to get off work, so let's write it here first. In fact, it is very simple to publish a cxf restful and soap. There are a lot of online examples. If it is deployed in an osgi environment. It is recommended to use karaf or servicemix.