JNET is a technology used for modelling graphical networks however not much technical information is available on the topic apart from the link http://graphics1.wdf.sap.corp:1080/jnet/Home.html. One would find it extremely difficult to locate a colleague who has worked on a project consuming JNET for modelling. This does not leave too much room but to explore the area by debugging some sample programs available in a few SAP systems. Hence I want to pen my understanding and experiences which I am sure will be helpful for colleagues who wish to use this technology by integrating in ABAP GUI. It is assumed that the developer who reads this document is aware of XML basics.
This Document will cover the following topics:
1. Introduction
2. Installation : Java 1.7 Vs Java 1.8
3. Pre-requisite notes
4. Pre-requisite SICF activations
5. Program structure
JNet is a generic editor for network graphics. It can be used to display anything that can be visualized as a set of nodes and links between nodes.
Figure 1
For more details, please refer to
http://graphics1.wdf.sap.corp:1080/jnet/Home.html
Please refer to http://graphics1.wdf.sap.corp:1080/jnet/Download.html
Java 1.7 requires JNET installation as part of GUI installer.
Figure 2
Java 1.8 does not require such specific installation. However a few notes needs to be installed in the system for Java 1.8 to be workable. Please refer to section 5.
1538367 | WDA: HTTP 404 when accessing "frog.jar" |
1637307 | new method GET_THEMENAME in CL_GUI_RESOURCES |
1693098 | ValueSuggest in accessibility mode |
1721445 | WDA: ACF control - Browser no longer responds |
1812323 | Sessions are not reduced in Web Dynpro ABAP |
1832111 | Popup window doesn't close when fired the EXIT Plug |
1855672 | Firefox: buttonWidth remains unchanged |
1891893 | WDA: Adjusting the Web Dynpro ABAP renderings part 11 |
1958962 | Network/Gantt: Java security prompt: IMS: Mimes Part .IV |
1959347 | Network/Gantt: Java security prompt: IMS: Mimes Part II |
1978813 | Network/Gantt: Java security prompt: IMS: Mimes Part III |
1978815 | Network/Gantt: Java security prompt: IMS: Mimes Part IV |
1978998 | Network/Gantt: Java security prompt: IMS: Mimes Part I |
1979266 | Network/Gantt: Java security prompt: IMS: Mimes Part .I |
1979267 | Network/Gantt: Java security prompt: IMS: Mimes Part .II |
1979268 | Network/Gantt: Java security prompt: IMS: Mimes Part .III |
1984545 | Network/Gantt: Java security prompt: IMS: Mimes Part V |
1984558 | Network/Gantt: Java security prompt: IMS: Mimes Part .V |
1987719 | GOS: Attachment List not refreshed after deleting third atta |
2105752 | Abap corrections for note 2103687 |
2158689 | Subsequent correction to SAP Note 2103687 |
2164890 | JNET in SAP GUI support of HTTP (not only HTTPS) |
1926137 | New version of JNet/JGantt JAR files for WebDynpro/ABAP appl |
2103687 | New implementation of JNet and JGantt in SAP GUI for Windows |
2016249 | SAP GUI (for Windows) Error Message "JNet not installed" |
2103200 | JNet/JGantt with Java 8 - ClassNotFoundException: 'com.sap.t |
There are few SICF paths which need to be activated before JNET can be consumed.
/default_host/sap/public/bc/Webdynpro/sap
/default_host/sap/public/bsp/sap/public/graphics/jnet_handler
/default_host/sap/public/myssocntl
/default_host/sap/webcuif
Please refer to sample programs mentioned at the link http://graphics1.wdf.sap.corp:1080/jnet/Documentation.html.
In general any ABAP program which uses JNET consists of 3 parts.
Figure 3
As depicted in the diagram above, UI screen contains a customer container inside which a JNET container is embedded. Customer container needs to be created in the ABAP GUI screen and a JNET object of type CL_GUI_JNET needs to be embedded in this container. It works the way a Tree or ALV container is created and embedded. Please refer to the code snippet below.
CREATE OBJECT go_container
EXPORTING
CONTAINER_NAME = 'CUSTOM_CONTAINER'.
CREATE OBJECT go_jnet
EXPORTING
PARENT = go_container.
The exchange of data between JNet controller and the underlying programs is done via an XML. The XML has a pre defined structure and must be complied to so it can be parsed by JNet controller. This XML renders the intended graph on the layout and consists of the following parts.
Please note that the below XML code is for explanation purpose. For a complete XML please refer to http://graphics1.wdf.sap.corp:1080/jnet/Demos.html.
It contains all the type declarations that can be used as properties of a UI element within the JNET. This section contains the various Types of Colors, Labels, Edge, Nodes etc. the XML supports. For example
Color: <COLOR>
<rgb hex="#A5D7F7"/>
</type>
<rgb hex="#FC7171"/>
</type>
</COLOR>
Figure 4
Edge : <EDGE>
<color type="color.GAS"/>
</type>
<color type="color.OIL"/>
</type>
An Edge type GAS will show a different color. Similarly other properties of the edge can be set. For example the below edge type will be a non-movable, dashed edge.
<editprops><moveable>FALSE</moveable></editprops>
<stroke>DASHED</stroke>
</type>
Figure 5
Node :
<shape type="Box"><size>120,70</size>
<color><rgb>221,221,221</rgb></color>
<thickness>2</thickness>
</border>
<filled>TRUE</filled>
<layout type="Layout"/>
<fillColor><rgb>226,220,226</rgb></fillColor>
</shape>
<location originAtBox="CENTER,BOTTOM"/>
<halign>CENTER</halign>
<halignText>CENTER</halignText>
<valign>TOP</valign>
<valignText>TOP</valignText>
</label>
<label type="Label" index="2">
<location originAtBox="LEFT,25%" offset="20,0"/>
<valign>CENTER</valign>
<halign>LEFT</halign>
<valignText>CENTER</valignText>
</label>
<label type="Label" index="3">
<location originAtBox="LEFT,50%" offset="20,0"/>
<valign>CENTER</valign>
<halign>LEFT</halign>
<valignText>CENTER</valignText>
</label>
<label type="Label" index="4">
<location originAtBox="LEFT,75%" offset="20,0"/>
<valign>CENTER</valign>
<halign>LEFT</halign>
<valignText>CENTER</valignText>
</label>
<label type="LabelIcon" index="5">
<location originAtBox="LEFT,TOP" offset="4,24"/>
<valign>TOP</valign>
<halign>LEFT</halign>
</label>
</type>
As the name suggests this section contains the UI elements and the JNET layout. It also offers commands which a user can execute via buttons or context menu. Some of the commands are standard commands offered by JNET (example PRINT_PREVIEW, PRINT, ZOOM etc. ) and some are custom commands (example DisplayObj, EditLink etc.) freely created by the user. Standard commands are handled by JNET itself whereas custom commands need to be handled by explicit ABAP coding.
<!---Standard commands--->
<Command name="PRINT_PREVIEW" enabled="TRUE" visible="TRUE"/>
<Command name="PRINT" visible="TRUE"/>
<Command name="CUT" visible="FALSE"/>
<Command name="COPY" visible="FALSE"/>
<Command name="PASTE" visible="FALSE"/>
<Command name="UNDO" visible="FALSE"/>
<Command name="REDO" enabled="FALSE" visible="FALSE"/>
<Command name="FIND" visible="TRUE"/>
<Command name="ZOOM" visible="TRUE"/>
<Command name="NAVIGATE" visible="FALSE"/>
<Command name="OPTIONS" visible="TRUE"/>
<Command name="LAYOUT" visible="TRUE"/>
<Command name="LAYOUT_OPTIONS" visible="TRUE"/>
<Command name="FILTER" visible="TRUE"/>
<Command name="FILTER_OPTIONS" visible="TRUE"/>
<!---Custom commands-->
<Command name="CreateLink" visible="TRUE" text="Create Object Link"/>
<Command name="CreateObj" visible="TRUE" text="Create Network Object"/>
<Command name="EditLink" visible="TRUE" text="Edit Object Link"/>
<Command name="RemoveLink" visible="TRUE" text="Remove Object Link"/>
<Command name=" DisplayLink " visible="TRUE" text="Display Object Link"/>
<Command name="DisplayObj" visible="TRUE" text="Display Network Object"/>
</Commands>
This below section allows setting of UI properties of the JNET layout like Visibility of the status bar, visibility of the Tool bar, color etc. Context menu events like “OnSingleNodeSelect” (which gets fired when a node is right clicked) are also handled here. Commands which are intended to be called on right click of node can be defined under the XML tag <item command />. These commands can be handled in the ABAP code.
<StatusBar visible="TRUE"/>
<NavigationArea withZoom="TRUE"/>
<ToolBar visible="TRUE"/>
<MainContainer layout="SPLITPANE">
<ToolsArea layout="VERTICAL_FLOW" vAlignment="TOP" hGap="10">
<rgb>221,221,221</rgb>
</Background>
</ToolsArea>
<WorkArea layout="SCROLLEDPANE" scrollbars="ALWAYS">
<Background><rgb>255,255,255</rgb></Background>
<Show>FALSE</Show>
<Color><rgb>0,0,0</rgb></Color>
<Size>40,40</Size>
<DrawingSize>10,10</DrawingSize>
</Grid>
<PopupMenu event="OnSingleNodeSelect">
<Item command="DisplayObj"/>
<Item command="ObjStatInfo" separator="TRUE"/>
</PopupMenu>
<PopupMenu event="OnSingleEdgeSelect">
<Item command="DisplayLink"/>
<Item command="RemoveLink"/>
</PopupMenu>
</WorkArea>
</MainContainer>
</Components>
</UserInterface>
This section contains the actual Nodes and links shown on the JNET. The logic to generate this section of the XML is covered in section 7.3.1.2
Node section contains the Node data with properties like Type, ID etc.
<Graph version="1.0" type="Graph">
<node type=" NodeBasic " id="AB BT 0112123">
<locationalignment="TOPLEFT" coords="ABSOLUTE">0,0</location
<label index="1"/>
<label index="2">AB BT 0112123</label>
<label index="3">AB BATTERY</label>
<label index="4"/>
<label index="5"/>
</node>
<node type=" NodeBasic " id="FAC_GP_INV">
<location alignment="TOPLEFT" coords="ABSOLUTE">0,0</location>
<label index="1"/>
<label index="2">FAC_GP_INV</label>
<label index="3">FAC_GP_INV</label>
<label index="4"/>
<label index="5"/>
</node>
Edge section contains the Edge data with properties like Type, Id, Starting and Ending nodes. It also contains the direction from which the edge is originating. In the below screen shot, the edge is originating from the eastern side and going into the western side. Hence the position is marked as EAST to WEST.
Figure 6
<edge type="OIL" id="005056AC7E771EE5ABA3D7F5D8C95FA4">
<thickness>2</thickness>
<from node="AB BT 0112123" position="EAST" plug="00"/>
<to node="FAC_GP_INV" position="WEST" socket="01"/>
</edge>
</Graph>
This XML ( assume is stored in variable gv_xml) needs to be loaded in the JNET container via JNET command LOAD_DATA.
Call Method go_jnet->Load_data
Exporting
Xml = gv_xml
Once the custom container is created and XML ( with Type Repository and User Interface ) defined, an Event handler needs to be coded which will handle all the events triggered out of JNET. Please refer to code snippet below. A method on_event is created in a local class whose instance is go_event_handler.
SET HANDLER go_Event_handler->on_event FOR go_jnet.
Method on_event will have an importing parameter ‘EVENT’ which will contain the name of the event fired. For example
Event ID | Short Description |
Indicates that a custom (i.e. application specific) command was invoked (by the user or some external controller). | |
indicates that JNet was initiated (the applet's init() method) | |
indicates that a link was added to the graph (a lose edge was plugged into a node's socket) | |
indicates that a node was added to the graph | |
indicates that a node has been clicked (not just selected) |
ABAP integration of the events is explained in section 7.3.1.
Method on_event gets called when an action is carried out on JNET. The events are in the form of an XML which need to be broken down into commands (event name) and component (node/edge id). For example, when a node is clicked, NODE_SELECTED event gets fired. The event XML is similar to what is shown below.
<?xml version="1.0" encoding="UTF-8"?>
<JNetEvent id="NODE_SELECTED" jnet="AppWin0" component="AB BT 0112123">
<parameter>3</parameter>
</JNetEvent>
A transformation needs to be called, which will break it into subcomponents
Command or Event : NODE_SELECTED
Component or Id : AB BT 0112123
Transformation uml_class_diagram_jnet_event, as mentioned in the sample programs, can be called for this purpose.
CALL TRANSFORMATION uml_class_diagram_jnet_event
SOURCE XML iv_event
RESULT
id = lv_command
component = lv_component
node = lv_node.
Once the Event name is available, normal ABAP logic can be written for each event. There are further 2 parts to it
ABAP logic to capture entered data can be written as is done in normal ABAP. For example, if a node is required to be added via ‘NODE_ADDED’ event, a pop up/ screen with Node Id and other details can be called, where the user can enter node details. This can be captured in local internal tables and work areas. Once captured, XML parser logic needs to be called to modify the XML. This modified XML needs to be reloaded using the command mentioned below.
Call Method go_jnet->Load_data
Exporting
Xml = gv_xml
Type repository and User interface are usually static and the XML containing these 2 sections can be stored in MIME repository/local desktop from where it can be read into the ABAP program. An XML parser needs to be written to generate XML code in ‘Graph’ section of the XML. This is required because the JNET layout is required to be completely reloaded with the new XML. Unless the XML is modified with the newly added node and loaded again, changes will not be reflected on the JNET screen.
If the newly added node is FAC_GP_1, the XML needs to be modified with the below addition in the graph section.
<node type=" NodeBasic " id="FAC_GP_1">
<location alignment="TOPLEFT" coords="ABSOLUTE">0,0</location>
<label index="1"/>
<label index="2">FAC_GP_1</label>
<label index="3">FAC_GP_1</label>
<label index="4"/>
<label index="5"/>
</node>
Code snippet for the modifying the XML via ABAP parser is as shown below.
Parser needs to be initialized.
Variable initialization
Data :
lo_ixml TYPE REF TO if_ixml,
lo_doc TYPE REF TO if_ixml_document,
lo_streamf TYPE REF TO if_ixml_stream_factory,
lo_istream TYPE REF TO if_ixml_istream,
lo_parser TYPE REF TO if_ixml_parser,
…..
Parser Logic
lo_ixml = cl_ixml=>create( ).
lo_streamf = lo_ixml->create_stream_factory( ).
lo_istream = lo_streamf->create_istream_xstring( cv_xml ).
lo_doc = lo_ixml->create_document( ).
lo_parser = lo_ixml->create_parser( stream_factory = lo_streamf
istream = lo_istream
document = lo_doc ).
An internal table with the newly added node details ( Id, description etc. ) needs to be looped over
LOOP AT it_node ASSIGNING <ls_node_tmp>.
CLEAR: ls_node, lv_value.
CLEAR lt_attr.
ls_attr-name = 'type'.
ls_attr-value = <ls_node>-node_type.
APPEND ls_attr TO lt_attr.
ls_attr-name = 'id'.
ls_attr-value = <ls_node>-obj_id.
APPEND ls_attr TO lt_attr.
lo_elem = io_doc->create_element( name = 'node').
Loop at lt_attr INTO ls_attr.
lv_attr_name = ls_attr-name.
lv_attr_value = ls_attr-value.
lo_attribute = io_doc->create_attribute( name = lv_attr_name ).
lo_attribute->set_value( value = lv_attr_value ).
lo_elem->set_attribute_node( new_attr = lo_attribute ).
Endloop.
ENDLOOP.
The above logic will create the XML line
<node type=" NodeBasic " id="FAC_GP_1">
Other lines for nodes and edges can be created using similar logic in the above loop
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
4 | |
2 | |
2 | |
2 | |
2 | |
2 | |
1 | |
1 | |
1 | |
1 |