Creating JAX-WS webservice using Service Data Objects (SDO) instead of JAXB-boun...
source link: https://blog.jakubholy.net/2010/12/29/creating-jax-ws-webservice-using-service-data-objects-sdo-instead-of-jaxb-bound-pojos/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Creating JAX-WS webservice using Service Data Objects (SDO) instead of JAXB-bound POJOs
If you need to invoke a logic using Service Data Objects (SDOs) from a JAX-WS webservice under Websphere 7 without the SCA Feature Pack, it is possible to do it similarly to the old approach of generating a JAX-RPC webservice from a WSDL with an SDO facade (actually building on it).
The steps are:
- Use RAD to generate a JAX-RPC webservice from a WSDL with an SDO facade.
- Implement a JAX-WS webservice accessing directly its input as XML data (i.e. implement is as a WebServiceProvider for message payload)
- Use Transformer and StreamSource/Result to convert from/to String containing XML
- Copy the SDO-related classes from the JAX-RPC webservice to the JAX-WS one, exclude just the JAX-RPC webservice interface and implementation
- Adjust the generated EMFSOAPElementUtil - change (de)serialize methods to expect/produce a String instead of SOAPElement
- Put it all together in the WS implementation class created in #2
- Finishing touches - add conversion of org.eclipse.emf.ecore.xml.type.internal.XMLCalendar to javax.xml.datatype.XMLGregorianCalendar
Implementation steps in detail
1. Generating JAX-RPC webservice with an SDO facade
Follow the link above.Notice that it generates POJO interfaces for the data objects, their implementations that actually implement the required SDO's commonj.sdo.DataObject, and some factories for instantiating them.
2. Implementing a JAX-WS webservice accessing its data as XML (javax.xml.transform.Source)
Again, follow the corresponding link above.At the end, the code should look like this: LearningActivityRawXmlServiceImpl.java, part 1:
javax.xml.ws.ServiceMode(value=javax.xml.ws.Service.Mode.PAYLOAD)
@javax.xml.ws.WebServiceProvider(...)
public class LearningActivityRawXmlServiceImpl implements Provider<Source> {
private LearningActivityHttpBindingImplSDO sdoInstance_ = new LearningActivityHttpBindingImplSDO();
private LaSOAPElementUtil laUtil_ = new LaSOAPElementUtil();
@Override
public Source invoke(final Source request) {
final DataObject requestSDO = convertRequest(request);
final DataObject responseSDO = sdoInstance_.updateLearningActivity(requestSDO);
final Source response = convertResponse(responseSDO);
return response;
}
// ... other methods omitted ...
}
The classLaSOAPElementUtilhas been created by the JAX-RPC generator. LearningActivityHttpBindingImplSDO represents the code that accepts and produces an SDO.
To transform the Source to XML and DataObject:
private DataObject convertRequest(final Source request) {
final StringWriter requestXmlWriter = new StringWriter();
try {
final Transformer trans = TransformerFactory.newInstance().newTransformer();
trans.transform(request, new StreamResult(requestXmlWriter));
final String requestXml = requestXmlWriter.toString();
final DocumentRoot laRoot = (DocumentRoot) laUtil_.deserialize(requestXml);
final UpdateLearningActivityType updateLearningActivityParametersSDO = laRoot.getUpdateLearningActivity();
return (UpdateLearningActivityTypeImpl) updateLearningActivityParametersSDO;
} catch (Exception e) {
// TransformerException, IOException, SAXException
throw new RuntimeException("Conversion failed: " + e + ", in: " + request, e);
} catch (TransformerFactoryConfigurationError e) {
throw new RuntimeException("Transformation during conversion failed: " + e + ", in: " + request, e);
}
}
The classes com.ibm.w3.xmlns.ibmww.hr.learning.lms.br.la.DocumentRoot and ...la.UpdateLearningActivityType have been created by the JAX-RPC generator based on the WSDL and XSDs. laUtil_.deserialize(..) only invokes the (also generated) EMFSOAPElementUtil.deserialize(..), which we will adjust later on. Notice that we need to cast from the generated pure java interface to the implementation class (UpdateLearningActivityTypeImpl) because only it does implement DataObject.
To transform DataObject to XML and Source:
private Source convertResponse(final DataObject responseSDO) {
try {
final String responseXml = laUtil_.serialize((EDataObjectImpl) responseSDO);
final Source response = new StreamSource(new StringReader(responseXml));
return response;
} catch (IOException e) {
throw new RuntimeException("Conversion failed: " + e + ", in: " + responseSDO, e);
} catch (SOAPException e) {
throw new RuntimeException("Conversion failed: " + e + ", in: " + responseSDO, e);
}
}
Again, laUtil_.serialize(..) only invokes the EMFSOAPElementUtil.serialize(..).
4. Adjust the generated EMFSOAPElementUtil to use XML String instead of SOAPElement
While the JAX-RPC generated EMFSOAPElementUtil uses SOAPElement, we need to use Strings containing XML and therefore will adjust the signature and bodies of the (de)serialization methods slightly:EMFSOAPElementUtil.java (part):
public EDataObjectImpl deserialize (final String xml)
throws IOException, SAXException
{
// Change: the inputStream is created from a String and not from a SOAPElement
final XMLResourceImpl res = (XMLResourceImpl)factory.createResource(URI.createURI("*.xml"));
final InputStream inputStream = new ByteArrayInputStream(xml.getBytes("UTF-8"));
res.load(inputStream, null);
final EDataObjectImpl document = (EDataObjectImpl)res.getContents().get(0);
return document;
}
public String serialize ( EDataObjectImpl document )
throws IOException, SOAPException
{
XMLResourceImpl res = (XMLResourceImpl)factory.createResource(URI.createURI("*.xml"));
res.getContents().add(document);
res.getDefaultSaveOptions().put(XMLResource.OPTION_DECLARE_XML,Boolean.FALSE);
res.setEncoding("UTF-8");
// Changed below - save into a StringWriter
final StringWriter outputXmlWriter = new StringWriter();
res.save(outputXmlWriter,null);
return outputXmlWriter.toString();
}
Don't worry about the XMLResourceImpl and similar stuff, it has been generated by the JAX-RPC tool.
6. Finishing touches - add conversion of XML Calendar
While JAX-RPC uses javax.xml.datatype.XMLGregorianCalendar, the EMF-based SDO implementation uses an incompatible org.eclipse.emf.ecore.xml.type.internal.XMLCalendar and it's therefore necessary to convert the former to the latter in each eSet(..) method of the generated data objects.Of course this is necessary only if any of the JAX-RPC generated data objects use XMLGregorianCalendar.
The conversion utility ConversionUtils.java:
import java.util.GregorianCalendar;
import java.util.TimeZone;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import org.eclipse.emf.ecore.xml.type.internal.XMLCalendar;
public class ConversionUtils {
public static XMLGregorianCalendar convertEmfToXmlCalendar(final XMLCalendar emfCalendar) {
final GregorianCalendar gregCal = new GregorianCalendar();
gregCal.setTime(emfCalendar.getDate());
gregCal.setTimeZone(TimeZone.getTimeZone("GMT"));
try {
final XMLGregorianCalendar xmlGregCal = DatatypeFactory
.newInstance().newXMLGregorianCalendar(gregCal);
return xmlGregCal;
} catch (DatatypeConfigurationException e) {
e.printStackTrace();
}
return null;
}
}
Adding the conversion to each of the affected data objects' eSet method:
// In a generated data class extending org.eclipse.emf.ecore.sdo.impl.EDataObjectImpl
public void eSet(int featureID, Object newValue)
{
if (newValue instanceof XMLCalendar) {
newValue = ConversionUtils.convertEmfToXmlCalendar((XMLCalendar) newValue);
}
switch (featureID)
{
...
}
super.eSet(featureID, newValue);
}
That's it, folks.
Recommend
-
65
一、课程介绍直接开门见山吧,在学习之前阿笨想问大家一句,关于WebService远程过程调用技术(RPC) 你真的会了吗?不要跟老夫扯什么WebService技术已经过时,如果你的内心有在偷偷告诉你其实我是真的不会WebService的话,那么恭喜你,因为你在这茫茫的IT编程世界里...
-
42
再谈用CXF框架开发WebService服务(4.1)
-
52
webservice简介:WebService技术,能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件,就可相互交换数据或集成。依据WebService规范实施的应用之间,无论它们所使用的语言、平台或内部协议是什么,都可以相互交换数据。WebService是自描述、...
-
54
WebService实战经验分享 说到WebSerivce,会想到很久很久前的SOAP,第一次看到的时候,觉得就一个神马。在.Net环境下使用过,导入WebService,直接使...
-
38
README.md GeoIP2 PHP API Description This package provides an API for the GeoIP2 w...
-
39
README.md 스프링부트2로 웹서비스 출시하기 (프리렉) 예제 코드 오타 & 오류 제보 상단의
-
35
程序员 - @Lancerer - 有用的大佬请问一下,WebService 的连接超时,和读取超时问题怎么处理
-
9
Jana De Klerk September 28, 2022 3 minute read
-
7
-
5
Jonathan Francis January 24, 2022 5 minute read...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK