cancel
Showing results for 
Search instead for 
Did you mean: 

Calling New Function Module from JAVA ISA b2b

Former Member
0 Kudos

I need to call a new function module which accepts some parameters as input and

returns some result parameters back as output.

These returned value needs to be displayed on the JSP pages of ISA B2B applications.

Can someone please guide me and provide code snippet on how to do this?

Thanks in advance.

Points will be awarded for all relevant and helpful answers.

Accepted Solutions (0)

Answers (2)

Answers (2)

Former Member
0 Kudos

Stride,

I did this on CRM ISA 4.0... I used the dev and extension guide as a basis - I think the ISA 5.0 guide has the examples and tutorials in a separate document that can also be downloaded from service.sap.com.

Here’s some info on how to do it although I can't guarantee this is the full solution or that it will work the same for ISA 5.0, and I will probably forget a lot of stuff as its been a few years since I did it! I also can’t guarantee it is the correct way to do it – but it worked! Basically, we built a link into the order overview page to display url’s to order tracking websites using an RFC on the backend CRM system. Hope it helps anyway.

1. Create RFC enabled function module in backend.

2. Edit file backendobject-config.xml in folder project_root\b2b_z\WEB-INF\xcm\customer\modification:-

[code] <backendobject

xmlns:isa="com.sapmarkets.isa.core.config"

xmlns:xi="http://www.w3.org/2001/XInclude"

xmlns:xml="http://www.w3.org/XML/1998/namespace">

<configs>

<!-- customer changes in backendobject-config should be done here by extending/overwriting the base configuration-->

<xi:include

href="$

  • Template for backend object in customer projects
  • Concrete implementation of a backend object
  • This implemenation demonstrates how a backend object
  • is used to communicate with the CRM system
  • @see com.ao.isa.backend.boi.Z_AOFuncBackend#getOrderDeliveryTrackingData(java.lang.String)
  • Interface used to communicate with a backend object
  • The purpose of this interface is to hide backend implementation details
  • from the business objects
  • Returns a vector of Z_OrderDeliverTracking objects containing data to link
  • to external delivery tracking websites
  • @param orderNo The sales order document number
  • @return A vector of order tracking objects
  • @return
  • @return
  • @return
  • @return
  • @return
  • @param string
  • @param string
  • @param string
  • @param string
  • @param string
/modification/backendobject-config.xml#xpointer(backendobject/configs/*)"/> <!-- This is an example customer extension. A new Backend Object is registered in the framework using XCM extension mechanism. --> <!-- If you write customer extensions you should register your backend objects in the same way. --> <!-- Please make sure that you use the correct base configuration (e.g. crmdefault for CRM or r3default, r3pidefault for R/3) --> <config isa:extends="../config[@id='crmdefault']"> <businessObject type="Z_AO_Custom" name="Z_AO_Custom" className="com.ao.isa.backend.crm.Z_AOFuncCRM" connectionFactoryName="JCO" defaultConnectionName="ISAStateless"/> </config> </configs> </backendobject> [/code] File com.ao.isa.backend.crm.Z_AOFuncCRM.java looks like this :- [code] package com.ao.isa.backend.crm; //jco imports import java.util.Vector; import com.ao.isa.backend.boi.Z_AOFuncBackend; import com.ao.isa.businessobject.order.Z_OrderDeliveryTrackingItem; import com.sap.mw.jco.JCO; import com.sap.mw.jco.JCO.ParameterList; import com.sapmarkets.isa.core.eai.BackendException; import com.sapmarkets.isa.core.eai.sp.jco.BackendBusinessObjectBaseSAP; import com.sapmarkets.isa.core.logging.IsaLocation; /** */ public class Z_AOFuncCRM extends BackendBusinessObjectBaseSAP implements Z_AOFuncBackend { // initialize logging private static IsaLocation log = IsaLocation.getInstance(Z_AOFuncCRM.class.getName()); /* (non-Javadoc) */ public Vector getOrderDeliveryTrackingData(String orderNo) { Vector urlData = new Vector(); try { // get Java representation of function module JCO.Function func = getDefaultJCoConnection().getJCoFunction( "Z_BAPI_CRM_ORDER_TRACKING_URLS"); // provide export parameters ParameterList params = func.getImportParameterList(); params.setValue(orderNo, "ORDER_NO"); func.setExportParameterList(params); // execute function getDefaultJCoConnection().execute(func); // get result table JCO.Table table = func.getTableParameterList().getTable("TRACKING_DATA"); int numRows = table.getNumRows(); for (int i = 0; i < numRows; i++) { // get row table.setRow(i); // create a new Z_orderdeliverytracking object Z_OrderDeliveryTrackingItem trackItem = new Z_OrderDeliveryTrackingItem( table.getString(0), table.getString(1), table.getString(2), table.getString(3), table.getString(4)); urlData.addElement(trackItem); trackItem = new Z_OrderDeliveryTrackingItem(); } return urlData; } catch (BackendException bex) { // The following key has to be added to WEB-INF/classes/ISAResources.properties // in order to see the exception correctly log.config("ao.b2b.order.error.getOrderTrackingURLs", bex); } return null; } } [/code] And file com.ao.isa.backend.boi.Z_AOFuncBackend.java looks like this:- [code] package com.ao.isa.backend.boi; //package java.ao.com.ao.isa.backend.boi; import java.util.Vector; import com.sapmarkets.isa.core.eai.sp.jco.JCoConnectionEventListener; /** */ public interface Z_AOFuncBackend { /** */ public Vector getOrderDeliveryTrackingData(String orderNo); } [/code] Whilst file com.ao.isa.businessobject.order.Z_OrderDeliveryTrackingItem.java looks like this:- [code] package com.ao.isa.businessobject.order; // Referenced classes of package com.sapmarkets.isa.businessobject.order: // PaymentType public class Z_OrderDeliveryTrackingItem // extends SalesDocument implements OrderData { private String deliveryDocNo; private String goodsIssuedDate; private String consignmentNo; private String status; private String url; public Z_OrderDeliveryTrackingItem() { } public Z_OrderDeliveryTrackingItem( String delDocNo, String GIDate, String consNo, String status, String url) { this.setDeliveryDocNo(delDocNo); this.setGoodsIssuedDate(GIDate); this.setConsignmentNo(consNo); this.setStatus(status); this.setUrl(url); } /** */ public String getConsignmentNo() { return consignmentNo; } /** */ public String getDeliveryDocNo() { return deliveryDocNo; } /** */ public String getGoodsIssuedDate() { return goodsIssuedDate; } /** */ public String getStatus() { return status; } /** */ public String getUrl() { return url; } /** */ public void setConsignmentNo(String string) { consignmentNo = string; } /** */ public void setDeliveryDocNo(String string) { deliveryDocNo = string; } /** */ public void setGoodsIssuedDate(String string) { goodsIssuedDate = string; } /** */ public void setStatus(String string) { status = string; } /** */ public void setUrl(String string) { url = string; } } [/code] 3. Edit file bom-config.xml in folder project_root\b2b_z\WEB-INF\xcm\customer\modification :- [code] <BusinessObjectManagers xmlns:isa="com.sapmarkets.isa.core.config" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xml="http://www.w3.org/XML/1998/namespace"> <!-- customer changes in bom-config should be done here by extending/overwriting the base configuration--> <xi:include href="$/modification/bom-config.xml#xpointer(BusinessObjectManagers/*)"/>

<!-- This is an example Business Object Manager. It can act as template for customer written Business Object Managers -->

<BusinessObjectManager

name="Z_AO-BOM"

className="com.ao.isa.businessobject.Z_AOBusinessObjectManager"

/>

</BusinessObjectManagers>

[/code]

File com.ao.isa.businessobject.Z_AOBusinessObjectManager.java looks like this:-

[code] package com.ao.isa.businessobject;

// Internet Sales imports

import com.sapmarkets.isa.core.businessobject.management.BOManager;

import com.sapmarkets.isa.core.businessobject.management.DefaultBusinessObjectManager;

import com.sapmarkets.isa.core.businessobject.BackendAware;

/**

  • Template for a custom BusinessObjectManager in customer projects

*/

public class Z_AOBusinessObjectManager

extends DefaultBusinessObjectManager

implements BOManager, BackendAware {

// key used for the backend object in customer version of backendobject-config.xml

public static final String CUSTOM_BOM = "Z_AO-BOM";

// reference to backend object

private Z_AOFunc mCustomBasket;

/**

  • constructor

*/

public Z_AOBusinessObjectManager() {

}

/**

  • Method is called by the framework before the session is invalidated.

  • The implemenation of this method should free any allocated resources

*/

public void release() {

}

/**

  • Returns custom business object

*/

public Z_AOFunc getCustomBasket() {

if (mCustomBasket == null) {

mCustomBasket = new Z_AOFunc();

assignBackendObjectManager(mCustomBasket);

}

return mCustomBasket;

}

}

[/code]

And uses file com.ao.isa.businessobject.Z_AOFunc.java which looks like this:-

[code]

package com.ao.isa.businessobject;

// Internet Sales imports

import com.sapmarkets.isa.core.businessobject.BOBase;

import com.sapmarkets.isa.core.businessobject.BackendAware;

import com.sapmarkets.isa.core.eai.BackendObjectManager;

import com.sapmarkets.isa.core.eai.BackendException;

import com.sapmarkets.isa.core.logging.IsaLocation;

// custom imports

import com.ao.isa.backend.boi.Z_AOFuncBackend;

import java.util.Vector;

/**

  • Template for business object in customer projects

*/

public class Z_AOFunc extends BOBase implements BackendAware

{

// initialize logging

private static IsaLocation log =

IsaLocation.getInstance(Z_AOFunc.class.getName());

private BackendObjectManager bem;

private Z_AOFuncBackend backendAOBasket;

/**

  • Returns a reference to the backend object. The backend object

  • is instantiated by the framework.

  • @return a reference to the backend object

*/

private Z_AOFuncBackend getCustomBasketBackend()

{

if (backendAOBasket == null)

{

//create new backend object

try

{

backendAOBasket =

(Z_AOFuncBackend) bem.createBackendBusinessObject(

"Z_AO_Custom");

// the backend object is registered in customer version

// of backendobject-config.xml using the 'Z_AO_Custom' type

}

catch (BackendException bex)

{

// The following key has to be added to WEB-INF/classes/ISAResources.properties

// in order to see the exception correctly

log.config("ao.b2b.order.error.getOrderTrackingURLs", bex);

}

}

return backendAOBasket;

}

/**

  • This method is needed when a business object has a corresponding

  • backend object.

*/

public void setBackendObjectManager(BackendObjectManager bem)

{

this.bem = bem;

}

/**

  • Returns a vector of url links for tracking

  • @return vector of urls

*/

public Vector getOrderDeliveryTrackingData(String orderNo)

{

// the call is delegated to the CRM aware backend object

return getCustomBasketBackend().getOrderDeliveryTrackingData(orderNo);

}

}

[/code]

4. Edit file config.xml in folder project_root\b2b_z\WEB-INF to add custom actions (the section below is just the custom stuff added at the end of the file – the Z_orderTracking is the relevant one) :-

[code] <!-- Begin of custom AO action definitions -->

<action path="/b2b/Z_orderTracking" type="com.ao.isa.order.actions.Z_OrderTrackingAction">

<forward name="success" path="/b2b/order/Z_orderTracking.jsp"/>

</action>

<action path="/catalog/Z_displaySVGPage" type="com.ao.isa.catalog.actions.Z_SVGPageAction">

<forward name="success" path="/catalog/Z_SVG_fs.jsp"/>

</action> [/code]

Which points at Java file com.ao.isa.order.actions.Z_OrderTrackingAction.java which looks like this :-

[code] package com.ao.isa.order.actions;

// internet sales imports

import com.sapmarkets.isa.core.BaseAction;

import com.sapmarkets.isa.core.UserSessionData;

// struts imports

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

import org.apache.struts.action.ActionForm;

// servlet imports

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.ServletException;

// Internet Sales imports

import com.ao.isa.businessobject.Z_AOBusinessObjectManager;

import java.util.Vector;

/**

  • This action acts as a template for customer extensions

*/

public class Z_OrderTrackingAction extends BaseAction

{

/**

  • This method is called by the ISA Framework when the

  • action is executed

*/

public ActionForward doPerform(

ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response)

throws ServletException

{

// get user session data object

UserSessionData userSessionData =

UserSessionData.getUserSessionData(request.getSession());

// gettting custom BOM

Z_AOBusinessObjectManager myBOM =

(Z_AOBusinessObjectManager) userSessionData.getBOM(

Z_AOBusinessObjectManager.CUSTOM_BOM);

// get the order number being processed

String orderDocNumber = request.getParameter("orderNo");

// pass the order number back to the page

request.setAttribute("orderNo", orderDocNumber);

if (orderDocNumber != null)

{

// Get a vector of delivery tracking objects from lower layers (Business Object layer =>

// Business Logic Service Layer)

Vector trackingTable =

myBOM.getCustomBasket().getOrderDeliveryTrackingData(

orderDocNumber);

String error = "";

if (trackingTable != null)

{

if (trackingTable.size() == 0)

{

error = "true";

}

else

{

error = "false";

}

}

else

{

error = "true";

}

request.setAttribute("errorMessage", error);

request.setAttribute("trackingTable", trackingTable);

}

return mapping.findForward("success");

}

}

[/code]

5. I added the call to the function module for page orderstatusdetail.jsp in folder project_root\b2b_z\b2b\order to display a custom page Z_orderTracking.jsp in the same folder. To do this I added a link into the HTML to call a JavaScript function that passed the current order number to the /b2b/Z_orderTracking.do actionhandler mapped in the config.xml file.

So, in summary! Create an RFC; define business managers for it in the XML files; create a new Strut action and supporting Java class; create all the Java class’ for the managers.

I hope this makes some sense!

Gareth.

Former Member
0 Kudos

Hi! Stride,

What i understood from your problem is, you have to show the output of a R/3 function module into a JSP page, if my understanding is correct then i think you can use JCO Connection in your JSP page and can call the function module.

regards,

Mithileshwar

Former Member
0 Kudos

Yes you understood me correct.

But can i directly call a Function Module from JSP using JCo.

Do you have sample code which can do that?

Thanks

> Hi! Stride,

> What i understood from your problem is, you have to

> show the output of a R/3 function module into a JSP

> page, if my understanding is correct then i think

> you can use JCO Connection in your JSP page and can

> call the function module.

>

> regards,

> Mithileshwar

Mithileshwar

Former Member
0 Kudos

Hi Stride,

I think that should be possible (I don't have code examples to hand sorry) but I'm not sure it is the best approach in the Struts framework as you would effectively be going against the MVC approach. If you do a bit of searching/digging around through this forum I'm sure there are a few posts about calling FM's via JCo or search the Blogs as I'm almost 100% there is at least one about using JCo (you may even be able to just lift some of the code I have posted above as it is still using JCo) but as I say, I wouldn't recommend this approach in the ISA framework environment.

Do you want to call the module to get results based on the content of the current JSP (i.e. react to a button press after entering data) or simply display extra data in the page before it is rendered? (This will have an impact I guess on how you could do this.)

Gareth.

Former Member
0 Kudos

Thanks Gareth

I will look around and gather some more information from the forums and blogs.

I realize that putting business logic and connection logic in JSP is not the correct

approach.

There were some constraints with our NWDS etc and hence we had to resort to a

quick JSP based approach.

To answer your question about the event on which the data needs to be displayed:

Whenever the JSP page is rendered or refreshed the BAPI/FM call needs to be made and the values need to be displayed?

Former Member
0 Kudos

> To answer your question about the event on which the

> data needs to be displayed:

>

> Whenever the JSP page is rendered or refreshed the

> BAPI/FM call needs to be made and the values need to

> be displayed?

Stride,

In that case the "best" solution, although not necessarily the easist or most efficient would be to add an extra step into the config.xml file directly preceeding the action that displays the jsp page you wish to change - so that whenever the "displayStridesJSPPage" action is called it actually defers to a custom Java action handler which then forwards onto the standard JSP page. This would of course be reliant on all the random code I posted above being in place to enable the backend communication

I'm honestly not sure one way or the other if a straight JCo call from a JSP page is possible in the ISA framework - it would be interesting to find out if it was.

For what its worth, when I started working on an ISA solution for one of our customers a couple of years ago, I spent ages getting to a usable working environment with NWDS. I think ISA 5.0 is better in this sense than 4.0 was but even so, my impression is that it isn't the best working environment. A lot of my initial development was done using notepad and a combination of windows explorer and WinRar to manage my project! I did eventually manage to import and work with the ISA project in NWDS that I was productive but could never reproduce the setup on other machines. So I completely understand your pains with the NWDS and ISA working environment!

Gareth.