on 11-05-2007 3:17 AM
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.
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.
Heres 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 cant guarantee it is the correct way to do it but it worked! Basically, we built a link into the order overview page to display urls 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="$
/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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
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.
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?
> 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.
User | Count |
---|---|
94 | |
11 | |
10 | |
9 | |
9 | |
7 | |
6 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.