cancel
Showing results for 
Search instead for 
Did you mean: 

How to create a web service & expose it to remote systems?

dynamolalit
Champ on-the-rise
Champ on-the-rise
Hi,

I need to create a web service which gives me top n users in repository to be exposed to one of our other systems consuming web services.

I am clueless about how to create a web service as a java class at all in alfresco & exposing it & forming WSDL from it.

Not much of the information is available in wiki.They are simple examples not serving full purpose.

Also i know that Alfresco uses Axis so web services functionality is included in it.

Can anyone help me out on this?
8 REPLIES 8

openpj
Elite Collaborator
Elite Collaborator
You need to download the Alfresco SDK importing all the existing projects in your IDE (for instance Eclipse).
Then you can add in your classpath all the dependencies of the project named SDK AlfrescoRemote.
In this way you can use the Alfresco Web Service Client that is a precompiled Java client stub that allows you to perform remotely operations against the repository.
You can take a look at the sample code in the Alfresco SDK, specifically in the project named SDK WebServiceSamples.

Here you can find more information about the Alfresco Web Services API:
http://wiki.alfresco.com/wiki/Alfresco_Content_Management_Web_Services

Hope this helps.

dynamolalit
Champ on-the-rise
Champ on-the-rise
Hi,

Thanks for your reply.

I am newbie to Web Services arena,sorry if i complicate.

I have configured SDK on Eclipse & all projects are working fine.

But i have specific requirement to generate WSDL files  & expose these WSDL files to another platform.

This mail platform should call Alfresco functionality contained in my web services using these WSDLs typically by creating a jar out of these classes & WSDLs and place it inside {Alf_home}/WEB-INF/lib.

Now any user can call these WSDLs & get desired results.

I have tried a sample & created a Hello World java Web service using eclipse.

Java class


package com.xxxx.km.alfresco.webservice;

public class TestWebServiceSOAP {

   
   
   public String test(){
      String str = "test";
      return str;
   }

}


I have placed webserviceclient.properties under {Alf_home}/WEB-INF/classes/alfresco/extension

#
# Set the following property to reference the Alfresco server that you would like web service client
# to communicate with
repository.location=http://x.x.x.x:8080/alfresco/api

I have WSDL file also as below


<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://webservice.alfresco.km.xxxx.com" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://webservice.alfresco.km.xxxx.com" xmlns:intf="http://webservice.alfresco.km.xxxx.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!–WSDL created by Apache Axis version: 1.4
Built on Apr 22, 2006 (06:55:48 PDT)–>
<wsdl:types>
  <schema elementFormDefault="qualified" targetNamespace="http://webservice.alfresco.km.xxxx.com" xmlns="http://www.w3.org/2001/XMLSchema">
   <element name="test">
    <complexType/>
   </element>
   <element name="testResponse">
    <complexType>
     <sequence>
      <element name="testReturn" type="xsd:string"/>
     </sequence>
    </complexType>
   </element>
  </schema>
</wsdl:types>

   <wsdl:message name="testResponse">

      <wsdl:part element="impl:testResponse" name="parameters"/>

   </wsdl:message>

   <wsdl:message name="testRequest">

      <wsdl:part element="impl:test" name="parameters"/>

   </wsdl:message>

   <wsdl:portType name="TestWebServiceSOAP">

      <wsdl:operation name="test">

         <wsdl:input message="impl:testRequest" name="testRequest"/>

         <wsdl:output message="impl:testResponse" name="testResponse"/>

      </wsdl:operation>

   </wsdl:portType>

   <wsdl:binding name="TestWebServiceSOAPSoapBinding" type="impl:TestWebServiceSOAP">

      <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http'/>

      <wsdl:operation name="test">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="testRequest">

            <wsdlsoap:body use="literal"/>

         </wsdl:input>

         <wsdl:output name="testResponse">

            <wsdlsoap:body use="literal"/>

         </wsdl:output>

      </wsdl:operation>

   </wsdl:binding>

   <wsdl:service name="TestWebServiceSOAPService">

      <wsdl:port binding="impl:TestWebServiceSOAPSoapBinding" name="TestWebServiceSOAP">

         <wsdlsoap:address location="http://localhost:8080/Test123/services/TestWebServiceSOAP'/>

      </wsdl:port>

   </wsdl:service>

</wsdl:definitions>



Now in WSDL file, i replaced

<wsdlsoap:address location="http://localhost:8080/Test123/services/TestWebServiceSOAP'/>

with

<wsdlsoap:address location="http://x.x.x.x:8080/alfresco/api/AlfWebService/services/TestWebServiceSOAP'/>

I am trying to access it using browser but getting this message:

Axis HTTP Servlet
Hi, you have reached the AXIS HTTP Servlet. Normally you would be hitting this URL with a SOAP client rather than a browser.

In case you are interested, my AXIS transport name appears to be 'http'

Now i am not sure weather my web service is deployed or not.

Any idea how to go forward from here.

dynamolalit
Champ on-the-rise
Champ on-the-rise
Hi,

Now i am able to develop & test a hello world web service in Alfresco.

Steps to create a custom web service in alfresco are as below:

1. Using Eclipse , i created a dynamic web project.
2. Then i created a hello world java class outputting "Hello World".
3. Then i created a web service using this java class, Eclipse generated a wsdl file.
4. I updated original <wsdlsoap:address> tag to <wsdlsoap:address location="http://localhost:8080/alfresco/api/TestWebServiceSOAP'/> in created wsdl file.
5. I deployed that wsdl to alfresco under {Alf_Home}\webapps\alfresco\wsdl .
6. Then i copied contents of deploy.wsdd to {Alf_Home}\webapps\alfresco\WEB-INF\server-config.wsdd.
7. Then i created a jar out of my eclipse project & placed @  {Alf_Home}\webapps\alfresco\WEB-INF\lib.
8. Restarted alfresco.
9. Using SOAPUI, i tested it & it is working fine.

So far so good. Smiley Happy

Now on same path , i developed a web service to search top users in repository.

But when i am trying to generate wsdl out of it, i am getting following message on eclipse.

The service class "com.xxxx.km.alfresco.webservice.SearchTopContributorWebService" does not comply to one or more requirements of the JAX-RPC 1.1 specification, and may not deploy or function correctly.
  The method "sortByValue" on the service class "com.xxxx.km.alfresco.webservice.SearchTopContributorWebService" uses a data type, "java.util.Map", that is not supported by the JAX-RPC specification. Instances of the type may not serialize or deserialize correctly. Loss of data or complete failure of the Web service may result.
  The method "sortByValue" on the service class "com.xxxx.km.alfresco.webservice.SearchTopContributorWebService" uses a data type, "java.util.Map", that is not supported by the JAX-RPC specification. Instances of the type may not serialize or deserialize correctly. Loss of data or complete failure of the Web service may result.

Now when i ignore it & click on finish, i am getting this error & not able to create wsdl file out of it.


IWAB0398E Error in generating WSDL from Java:  java.lang.ClassCastException: org.apache.axis.encoding.ser.BeanSerializer cannot be cast to org.apache.axis.encoding.Serializer
    java.lang.ClassCastException: org.apache.axis.encoding.ser.BeanSerializer cannot be cast to org.apache.axis.encoding.Serializer
    at org.apache.axis.encoding.ser.BaseSerializerFactory.getSpecialized(BaseSerializerFactory.java:165)
    at org.apache.axis.encoding.ser.BaseSerializerFactory.getSerializerAsInternal(BaseSerializerFactory.java:91)
    at org.apache.axis.encoding.ser.BaseSerializerFactory.getSerializerAs(BaseSerializerFactory.java:82)
    at org.apache.axis.encoding.ser.BeanSerializerFactory.getSerializerAs(BeanSerializerFactory.java:64)
    at org.apache.axis.wsdl.fromJava.Types.makeTypeElement(Types.java:1838)
    at org.apache.axis.wsdl.fromJava.Types.writeTypeForPart(Types.java:421)
    at org.apache.axis.wsdl.fromJava.Emitter.writePartToMessage(Emitter.java:1909)
    at org.apache.axis.wsdl.fromJava.Emitter.writeFaultMessage(Emitter.java:1822)
    at org.apache.axis.wsdl.fromJava.Emitter.writeMessages(Emitter.java:1143)
    at org.apache.axis.wsdl.fromJava.Emitter.writePortType(Emitter.java:1075)
    at org.apache.axis.wsdl.fromJava.Emitter.getWSDL(Emitter.java:484)
    at org.apache.axis.wsdl.fromJava.Emitter.emit(Emitter.java:331)
    at org.apache.axis.wsdl.fromJava.Emitter.emit(Emitter.java:430)
    at org.apache.axis.tools.ant.wsdl.Java2WsdlAntTask.execute(Java2WsdlAntTask.java:243)
    at org.eclipse.jst.ws.internal.axis.consumption.core.command.Java2WSDLCommand.executeAntTask(Java2WSDLCommand.java:180)
    at org.eclipse.jst.ws.internal.axis.consumption.core.command.Java2WSDLCommand.execute(Java2WSDLCommand.java:95)
    at org.eclipse.jst.ws.internal.axis.creation.ui.command.BUCodeGenOperation$BottomUpWSModifyOperation.execute(BUCodeGenOperation.java:116)
    at org.eclipse.jst.ws.internal.axis.creation.ui.command.BUCodeGenOperation.execute(BUCodeGenOperation.java:80)
    at org.eclipse.wst.command.internal.env.core.fragment.CommandFragmentEngine.runCommand(CommandFragmentEngine.java:419)
    at org.eclipse.wst.command.internal.env.core.fragment.CommandFragmentEngine.visitTop(CommandFragmentEngine.java:359)
    at org.eclipse.wst.command.internal.env.core.fragment.CommandFragmentEngine.moveForwardToNextStop(CommandFragmentEngine.java:254)
    at org.eclipse.wst.command.internal.env.ui.widgets.SimpleCommandEngineManager$6.run(SimpleCommandEngineManager.java:294)
    at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464)
    at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372)
    at org.eclipse.jface.wizard.WizardDialog.run(WizardDialog.java:944)
    at org.eclipse.wst.command.internal.env.ui.widgets.SimpleCommandEngineManager.runForwardToNextStop(SimpleCommandEngineManager.java:264)
    at org.eclipse.wst.command.internal.env.ui.widgets.WizardPageManager.runForwardToNextStop(WizardPageManager.java:91)
    at org.eclipse.wst.command.internal.env.ui.widgets.WizardPageManager.getNextPage(WizardPageManager.java:154)
    at org.eclipse.wst.command.internal.env.ui.widgets.SimpleWizardPage.getNextPage(SimpleWizardPage.java:136)
    at org.eclipse.jface.wizard.WizardDialog.nextPressed(WizardDialog.java:823)
    at org.eclipse.jface.wizard.WizardDialog.buttonPressed(WizardDialog.java:369)
    at org.eclipse.jface.dialogs.Dialog$2.widgetSelected(Dialog.java:624)
    at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:228)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003)
    at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3880)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3473)
    at org.eclipse.jface.window.Window.runEventLoop(Window.java:825)
    at org.eclipse.jface.window.Window.open(Window.java:801)
    at org.eclipse.ui.internal.actions.NewWizardShortcutAction.run(NewWizardShortcutAction.java:135)
    at org.eclipse.jface.action.Action.runWithEvent(Action.java:498)
    at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:584)
    at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:501)
    at org.eclipse.jface.action.ActionContributionItem$5.handleEvent(ActionContributionItem.java:411)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003)
    at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3880)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3473)
    at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2405)
    at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2369)
    at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2221)
    at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:500)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
    at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:493)
    at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
    at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:113)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:194)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:368)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:559)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:514)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1311)

I assume i am missing something.Is it a serialization issue or axis issue.

Can anyone help me here please.

mrogers
Star Contributor
Star Contributor
You are probably much better off using Web Scripts.   They are a lot easier than faffing with the SOAP machinery.

Now to answer your question
The types you can use with a web service are limited to a few "lowest common denominator" types.   In particular there is no key/value (Map) type in a web service.      You will probably need to replace your map with an array containing an element containing two values.

dynamolalit
Champ on-the-rise
Champ on-the-rise
Hi mrogers,

Thanks a lot for your reply.

I am doing Top Users operation using web scripts only but as  part of requirement, i need to expose this functionality as a web service.

My web service will interact with a mail platform which consumes it & do further processing.

Is there any way i can expose my web scripts as web service? Any wrapper or such thing.


AFAIK, web scripts are also based on web services.So does this mechanism exist?


Also regd Map/arraylist use in web services, i just found a workaround, i.e. to make them synchronized.

private Map<String,UserDetails> usageMap = Collections.synchronizedMap(new HashMap<String,UserDetails>());

It did the trick & i am able to generate wsdl & started testing using SOAPUI.

But i am  stuck up in getting services api as nodeservice.

I know that there is separate mechanism in alfresco web services to get these services.I am roaming around it.

Can anyone help me here??

sapkalnishikant
Champ in-the-making
Champ in-the-making
Hi, I am new to alfresco  i have followed steps that you have mentioned for exposing webservices  but i am not sure what do you mean by testing using soap Ui? is it means going to context url in my case
http://localhost:8080/alfresco/HelloAlfresco?wsdl
HelloAlfresco= my webservice ;
then its giving me a 404.
can you help me?

mrogers
Star Contributor
Star Contributor
Is there any way i can expose my web scripts as web service? Any wrapper or such thing.

AFAIK, web scripts are also based on web services.So does this mechanism exist?

No.  Web Scripts and Web Services are based on HTTP, that's the common denominator.     One of the big plus points with web scripts is that they dispense with the often excessive complexity of web services so a web script to web service wrapper would rather defeat some of the purpose of web scripts.   

It is however a perfectly good approach to expose the same model via web services AND web scripts, for example this is provided for the CMIS API.   The client can then choose which interface to use.

dynamolalit
Champ on-the-rise
Champ on-the-rise
Hi All,

Sorry for replying late.

Finally, i got my web service fine tuned. Smiley Happy

@ sapkalnishikant : I am using SOAPUI to unit test my web service. It acts like a web service client from which user can invoke web services by passing parameteres from console as below:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://webservice.alfresco.km.xxxx.com">
   <soapenv:Header/>
   <soapenv:Body>
      <web:startSearch>
         <web:location>all</web:location>
         <web:designation>all</web:designation>
         <web:noOfContributors>10</web:noOfContributors>
      </web:startSearch>
   </soapenv:Body>
</soapenv:Envelope>

Reg 404, i can see that your URL is not correct @ http://localhost:8080/alfresco/HelloAlfresco?wsdl.

You should use it like http://localhost:8080/alfresco/api/HelloAlfresco?wsdl as http://localhost:8080/alfresco/api is Alfresco web service end point.

Further , Alfresco behaves in such way that you can not hit wsdl directly, instead you should use a web service client to access the same.

Lets say if i access following URL of one of my web service @


http://localhost:8080/alfresco/api/SearchWebService
'>
http://localhost:8080/alfresco/api/SearchWebSer...


I am getting this message:


Axis HTTP Servlet
Hi, you have reached the AXIS HTTP Servlet. Normally you would be hitting this URL with a SOAP client rather than a browser.
In case you are interested, my AXIS transport name appears to be 'http'

Now coming to alfresco  services apis in web services, a number of stubs exists:


http://wiki.alfresco.com/wiki/Alfresco_Content_Management_Web_Services#Web_Services_Reference
'>
http:...


Alfresco web services use org.alfresco.webservice.types.Predicate as wrapper around lucene queries to search nodes in repository.

It works as follows:


// Getting reference to the RepositoryServiceSoapBindingStub.
RepositoryServiceSoapBindingStub repositoryService = WebServiceFactory.getRepositoryService();
// Getting reference to the AdministrationServiceSoapBindingStub.
AdministrationServiceSoapBindingStub adminService = WebServiceFactory.getAdministrationService();
String pathQuery = "/app:company_home/cm:"+ISO9075.encode("Required Path String");
//Creating Query for Web Service.
String kmWsQuery  = "PATH:\"/" + pathQuery + "//.\" AND TYPE:\"{http://www.alfresco.org/model/content/1.0}content\"";
Query userSearchQuery = new Query(Constants.QUERY_LANG_LUCENE,kmWsQuery);
logger.debug("userSearchQuery : "+userSearchQuery.getStatement());
//Using predicate for querying repository.
Predicate searchPredicate = new Predicate(null, STORE, userSearchQuery);
//Getting nodes as result.
Node[] nodes= repositoryService.get(searchPredicate);

Once you get nodes, you can get properties of a node as below:


for (Node node : nodes) {
org.alfresco.webservice.types.NamedValue[] nodeProperties = node.getProperties();
for (org.alfresco.webservice.types.NamedValue nodeProperty : nodeProperties) {   
if(nodeProperty.getName().endsWith(ContentModel.PROP_CREATOR.toString())){
String contentCreator = nodeProperty.getValue();      
….}                  

Further, for getting properties of a user, try following:


for (org.alfresco.webservice.types.NamedValue nodeProperty : nodeProperties) {   
if(nodeProperty.getName().endsWith(ContentModel.PROP_CREATOR.toString())){
String  contentCreator = nodeProperty.getValue();
//Getting user location for creator found above using RepositoryServiceSoapBindingStub.
org.alfresco.webservice.administration.UserDetails userDetails = adminService.getUser(contentCreator);
org.alfresco.webservice.types.NamedValue[] userProperties = userDetails.getProperties();
for(org.alfresco.webservice.types.NamedValue userProp : userProperties){
if(userProp.getName().endsWith(ContentModel.PROP_LOCATION.toString())){
String userLocation = userProp.getValue();
}                           
}      
….}

Point to be taken care is Predicate here as it is required for search in repository while working with alfresco web services. 😎

Finally, while working with wsdl files, update <wsdlsoap:address/> tag  in wsdl as below by pointing to your alfresco server as endpoint:

<wsdlsoap:address location="http://ur.server.ip.addessSmiley Tongueort/alfresco/api/SomeWebService'/>

Hope this helps!