Quantcast
Channel: SCN : Blog List - Java Development
Viewing all 50 articles
Browse latest View live

Expose a BAPI using JSON and REST

$
0
0

REST.

JSON.

 

These are the technologies you need when writing modern web applications. And that is what makes it so hard to use SAP together with modern web applications: Currently you only get REST from SAP with Gateway, but not JSON. OData comes from Microsoft and support is not as wide spread as someone expects. How OData does looks like? You can try it out by downloading the Gateway Trial from SCN or use the online demo system. To experiment with Gateway the usual flight example from SAP can be used.

 

To get the details of a specific flight:

http://gateway trial server:port/sap/opu/sdata/iwfnd/RMTSAMPLEFLIGHT/FlightCollection(carrid='AA',connid='0017',fldate='20110601')

 

Data returned from Gateway:

1gwodata.jpg

Instead of being able to use the data exposed by Gateway by the widely used Javascript frameworks like jQuery you need to find a OData plugin. Of course you can use SAP UI5, but what when you are forced to use jQuery, Sencha, Dojo or something else?

 

That’s a problem with SAP and ABAP in general: you have to wait until SAP implements missing functionality or someone posts it on Code Exchange or some other platform, and because of the limit resources available in the ABAP ecosystem this can take a while, costs some (serious amount of) money or will never happen. That’s where we can be happy that SAP also embraces the use of Java. As Java was made for the internet there is a huge Java community out there that most probably already developed a tool that fits your needs.

 

For exposing data as JSON in a REST-full way the tool available is: Jersey

 

After Jersey transformed the data, the response looks like:

1bapijson.jpg

Jersey needs Java 6 and runs in a servlet container. As NetWeaver CE >= 7.2 fulfills these requirements, Jersey can be used to transform Java objects into JSON and expose them using REST. NW CE comes with a framework for creating composite applications (CAF) that can consume BAPIs. CAF uses standard J2EE technology like JCA and Beans. This bean can be used by Jersey to automatically extract the data, transform it into JSON and make it accessible using REST.

 

Consuming a BAPI using CAF can be done with no coding involved at all as CAF comes with some nice wizards. Just map the input and output parameters and the code will be generated including the bean that can be used to interact with the BAPI. In the Jersey web application the URL and protocol get defined:

 

@GET
@Path("getFlight/carrid/{carrid}/connid/{connid}/fldate/{fldate}")
@Produces("application/json")

 

The CAF bean gets called using the parameters retrieved from the URL:


out = e.bapiFLIGHTGETDETAIL(null, null, null, carrid, connid, flightDate);

 

  That’s it. Jersey will do the rest:

3jsonfirebug.jpg

How the URL gets constructed is up to you, the parameters can be part of the URL as above or a query. You can also define if it is GET, POST, PUT, etc. If you want to do some coding you can adjust the output, or combine the result of several BAPIs into one Java object that JSON will expose.

 

Now that the BAPI can be accessed in a RESTful way and the data retrieved is in the JSON format, it’s easy to use the data in a Javascript framework like jQuery with Datatables:

4jquerytable.jpg

The actual coding for making the CAF bean accessible to Jersey and expose the data is less than 10 lines of code. From CAF to Jersey to a running HTML application it does not even take 30 minutes.

 

The framework I used for interacting with the ABAP system is CAF, a framework available for NetWeaver Java since a while (7.0): well documented enterprise ready and supported. If you want or need to expose your BAPI by REST and JSON or XML and you have a NetWeaver CE >= 7.2 (like Portal 7.3) available, you can start today. As your NW CE system is a separate one, upgrades won’t affect your backend system and as Jersey is also a separate application; changes to Jersey don’t affect your other CE server and applications. Of course you don’t need NW CE for using Jersey and CAF for interacting with BAPI. Every platform that Jersey supports and where you can use JCo from SAP to call a BAPI can be used like tomcat. It just means that some extra configuration and coding will be necessary. This also implies that your backend ABAP system can be used as long as a JCo connection to it is possible.


TextHelp - A Search Help API for JAVA

$
0
0

Inspired by SAP Search Help, I was desperate of making such a component in Java for Java Swing. I developed a reusable API named TextHelp and hosted the project on Google Code. I shared the link in SCN previously through Search Help for Java. Here I would like to share a sample program using TextHelp.

 

You can download the binary and documentation from the following link

 

http://freeze-cse.blogspot.com/p/texthelp_07.html

 

All you have to do is provide the database connection, the table name, columns to be shown and return value column (column from which the return value should be taken). TextHelp will show a dialog box automatically on key press (key should be provided at first). It is not having all the features of SAP Search Help. I tried to give a basic one, when I take it to further step I will share it with you for sure.

 

It is having only three classes and an interface.

  • TextHelp
  • TextHelpConfig
  • TextHelpListener
  • TextSelectedEvent

 

TextHelp

For each window in which one or more text fields that uses TextHelp, an instance of this class should be created. It contains the mappings of JTextFields and their corresponding TextHelpConfig

 

TextHelpConfig

This class contains the table name from which data should be fetched, fields that should be shown on text help dialog and the field from which data should be entered into the text field. For each text field, an instance of this object should be attached.

 

TextHelpListener

This is an interface. textSelected method of this interface’s implementation will be called after each successful selection from the dialog box.

 

TextSelectedEvent

TextSelectedEvent contains the selected text and the row number of the table.

 

The following is a sample implementation.

 

package texthelpdemo;

import com.fareez.swing.texthelp.TextHelp;
import com.fareez.swing.texthelp.TextHelpConfig;
import com.fareez.swing.texthelp.TextHelpListener;
import com.fareez.swing.texthelp.TextSelectedEvent;
import java.awt.FlowLayout;
import java.awt.event.KeyEvent;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

/**
 * A sample implementation
 * 
 * @author Fareez Ahamed K.N. freeze-cse.blogspot.com
 * 
 */
public class TextHelpDemo extends JFrame implements TextHelpListener {

    Connection conn;    TextHelp th;    JTextField tf;    JPanel panel;    JLabel cname;    TextHelpConfig thc;    TextHelpDemo() {        super("TextHelp");        tf = new JTextField(10);        cname = new JLabel();        try {            Class.forName("com.mysql.jdbc.Driver");            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "");            th = new TextHelp(conn,KeyEvent.VK_F1,this);        } catch (ClassNotFoundException ex) {            ex.printStackTrace();        } catch (SQLException ex) {            ex.printStackTrace();        }        getContentPane().setLayout(new FlowLayout());        getContentPane().add(new JLabel("Country"));        getContentPane().add(tf);        getContentPane().add(cname);        thc = new TextHelpConfig("countries","country_code", new String[] {"country_code","country_name"} );        try {            thc.setSortOrder(new String[]{ TextHelpConfig.DESC, TextHelpConfig.ASC } );            th.attach(tf, thc);            th.addTextHelpListener(this);        } catch (SQLException ex) {            ex.printStackTrace();        }        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        setSize(200,200);        setVisible(true);    }    public static void main(String args[])    {        TextHelpDemo test = new TextHelpDemo();    }    public void textSelected(TextSelectedEvent e) {        if(e.getTextField()==tf) {            try {                Statement stmt = conn.createStatement();                ResultSet rs = stmt.executeQuery("select country_name from countries where country_code='" + e.getSelectedText() +"'");                rs.next();                cname.setText(rs.getString(1));            } catch (SQLException ex) {                ex.printStackTrace();            }        }    }

}

 

I used MySQL as database here. The database contains a single table named countries with fields id, country_code and country_name. SQL to create the table and all the country names and codes are available at http://freeze-cse.blogspot.com/p/country-table.html.

 

Check out the output.

img1.PNG

On pressing F1

img2.PNG

After Selection

Hope it helps the Java Community.

 

Fareez Ahamed

freeze-cse.blogspot.com

Additional Accounting Document Posting During MIGO or MIGO_GI

$
0
0

Hello Folks,

        just thought of sharing a solution of a requirement with you. I need to post additional accounting document during goods issue of a material ( T CODE MIGO_GI or MIGO ). I achieved it using implementation of MB_DOCUMENT_BADI in method MB_DOCUMENT_UPDATE. I basically used BAPI_ACC_DOCUMENT_POST and as i have to do only GL relevent postings so i used "documentheader","accountgl",currencyamount" and "return" parameters of the BAPI. Some Key points.

 

1. Earlier i tried using MB_MIGO_BADI and method POST, but i failed to achieve my requirement as it is giving dump or FI interface accounting error.

2. So i used the above mentioned method, but do remember to use the above BAPI without the BAPI_TRANSACTION_COMMIT as it will result in a dump if you use that.

3. as the method MB_DOCUMENT_UPDATE is called in update mode so if you want to debug it, remember to put the update debugging on.

4.I didnt pass OBJ_TYPE, OBJ_KEY and OBJ_SYS parameters although in the bapi documentation it is written as required ones, but my code works fantastically by automatically determining the OBJ_TYPE as BKPFF.

5. Some of the dumps i got is like " abend error" if i was using BAPI_TRANSACTION_COMMIT and "system is cheking for MKPF as OBJECT TYPE although the checks were run for OBJECT TYPE BKPFF" and i remove those parameters as i told in step 4.

 

 

Regards

Animesh Sundriyal

Continuous integration

$
0
0

Continuous integration (CI) in software development as part of quality control is a hot topic. The idea is to ensure that the time needed to get a functionality working is decreased while at the same time improves the quality. This is done by giving instant feedback of how new code affects the overall solution. This behavior makes CI preferred for in agile projects, but is not limited to.

 

While the concept of CI isa convincing – or should be - to everyone that ever has coded a piece of software that does more than hello world, the implementation of CI is a complex task. Just using a CI system does not mean that you use CI. You have to provide test cases (a lot!), metrics about performance and code quality, collaboration tools, and so on. While a CI system can be used standalone, it should be part of several quality control solutions that work together.

How does CI work?

A CI system watches a code repository for changes. As soon as a change to the code base is committed, the CI system starts building the code and runs the quality tests. These can consists of unit tests, deploy, performance / functional / integration / etc tests and creates a report. Important here is that in case a job reports an error the developer that committed the new code gets informed that his/her code broke the build. The final result of the job is made public to all involved participants so everybody get an actual view on the state of the solution.

 

An important aspect of CI is that the whole process gets triggered when code gets committed. CI is not a nightly build. A best practice is to encourage developers to commit their code at least once a day. This does not mean that they only commit before leaving the office, all day code commit occur and throughout the day a new version of the software gets build and tested by the CI system.

Continuous Integration == Hard Work

As you can see in the above description, it’s not enough to simply have a CI system. You need to have a build system that works with the CI system. And only having a build that compiles is not enough: you have to provide test cases. You need unit tests that really test the code; functional tests like browsers; performance tests to know if the new functionality executes in the established time limits. Your CI system has to be able to automatically deploy the code to a system and to invoke other quality systems.


Before you can start using CI, you have to analyze your development infrastructure and ask some simple questions:

  • Does your development infrastructure provide the basics for CI?
  • Can you modularize your build?
  • Can you provide meaningful tests?
  • Do you have KPIs?
  • Do you know what other solutions are using the functionality of the application or may be affected by changing it (performance impact when running on the same server)
  • Many more

Why do all the hard work?

Looking at all the points and issues raised above, a simple question comes to mind: Why do all the work for my applications? The biggest issue with CI: you do not get immediate results. Contrary: you will slow down your development and add a lot of work load to everybody: not only the developers, but also to the people responsible for tests, the quality, the help desk and end users. The most important and critical part of CI are the tests. If you test too little or wrong, errors may slip through and manifest in production. On the other side, you cannot test too much J Creating tests needs time, more time than you think or the project manager is willing to spent and will never come to an end.

 

To start gathering tests it’s a good idea to look at the end users error reports already raised (and solved). These errors already occurred once and should never occur again. Once you have some useful tests you will see getting the first results: broken builds not because of compilation errors but because of errors found in the test cases. And the best thing is: automatically. Instead of letting the developer code his application and test it in DEV, later transport it to QA and run there some (manual) tests – too often this is done close the deadline of the project - the application is tested already in DEV. The QA team can focus on load testing and how the application performance with a realistic set of data. Short: errors like a not working submit button won’t be found in QA. A modular build process is only the first step: for an effective CI you’ll get a landscape that is fully modularized and automated. No need any more to do or wait for a manual transport, to start the tests, to wait for the test results: you get everything automatically.


Continuous integration and SAP

Looking at CI solutions available at the market and developer conference sessions it is clear that CI is no longer a niche idea. For several programming languages CI systems are available that integrate nicely with code revision systems and quality tools. Exception of the rule: SAP.


Automated builds, transports, deploys, tests, immediate feedback and transparency. Sounds convincing, still hard to achieve in an SAP centric landscape. Even when you solve the basic CI integration problems you still have to deal with how SAP is run. Ask yourself: an automated deploy to your QA system because a developer committed some source code: Is this possible? Does the governance of the system or transport management allow this? Can you run tests in the QA system on your own or only the QA team is allowed to do that (and has the tools). Another problem are the test cases.  You don’t get a set of tests from SAP nor test examples. You have to create your own set of tests. The CI system has to be able to trigger the tests: your QA software has to offer a remote start/control functionality.


What makes it hard to use CI together with SAP?

For most, SAP equals ABAP, but it’s more complex. There is NetWeaver ABAP, Java, on top of it specific solutions like CRM, SRM, BS, than the integration part, a lot of different technologies and so on. It is hard to predict what is effected when a function module is altered. What frontends are effected directly and what about the other transactions that use the FM? Or when the Java application writes slightly different data into the table? And will you mobile app developed with SUP still show the data correctly in the list?

 

ABAP development is a little bit different compared to what a CI normally expects. An ABAP developer works in the system, while a CI system needs to interact with the system from the outside: get the code, transport, deploy, run the tests. In ABAP there is not really a commit, and while recent versions of NetWeaver ABAP offers unit tests and eCATT, it’s not like you can do this with every version or get an external tool that triggers the tests. If you check the plugin list of Jenkins (https://wiki.jenkins-ci.org/display/JENKINS/Plugins), you can see that there are not SAP/ABAP specific plugins listed, making it hard to implement a useful CI solution in an ABAP landscape. Even when you use CI for your non-ABAP applications that use some ABAP functionality, a change to the ABAP code line won’t trigger the CI system.

 

For Java and SAP the situation might look better as Java is natively supported by CI systems like Jenkins. In reality it’s not much different than with ABAP. The developer uses SAP’s own Java SDK (NWDS) that comes with build in wizards for code generation and deploy. Additionally you get an external code revision system (NWDI), but working with it remotely is only doable – note: not easy - with tools from SAP. A big issue is to modularize the build, make the CI aware of NWDI and in case of WDJ: to write unit tests. WDJ applications are written in a mixture of XML and Java syntax that has the name Java in it, but at the same time is not Java. Then you have the DC and public part concept that creates more trouble and headaches than helps developers solving dependencies. Things get better for J2EE or SAP Portal developments as there you are actually developing in Java (constructors, method overloading, inheritance, polymorphism is available). Writing unit tests is like for every other J2EE application. You can use your own RCS, you can create your own maven of ant script for building the jar / war / ear files. It would be way easier to get started with CI for a SAP Java project if SAP provided maven/ant scripts and repositories for dependency management.


No continuous integration for SAP?

CI is not easy to implement, and even when a SAP wide implementation of CI is unlikely you should at least try it for your projects and applications. Start small. Get started with your infrastructure, select some tools, find out how to automate tasks and create test cases. Write unit tests for your code. Gather KPIs. The easiest start should be from the Java side and for J2EE projects as these come pretty close to non-SAP Java developments. CI scenarios and setup guides for these kinds of applications are easy to find.

SAP Java Connector 3.0.9 released

$
0
0

Yesterday I got th message internally that there is a new release of Java Connector (JCo) available.

 

Note 1671480 explains details, but for your convenience I copied the most important information, the fixes that have been achieved:

 

  1. A memory leak in the Java heap is recognized.
  2. A JCoException with the CPIC error message "client with wrong appc header version rejected" is thrown.
  3. An RfcGetException with message "Received a callback from the communication partner" was logged in the RFC error log file dev_jco_rfc.trc and maybe also some table parameters of a called Remote Function Module (RFM) are empty or do not contain the expected data.
  4. RFC logon attempts hang infinitely or take too long without being interrupted after 60 seconds or after the configured RFC connect timeout interval.
  5. Fields of type XSTRING contain one 0-byte value after setting a null-reference value into them.
  6. JCo trace information in JCoServer scenarios is missing when using a JCoServerRequestHandler instance (RFC request/response model).
  7. The properties 'jco.session_timeout' and 'jco.session_timeout.check_interval' cannot be set as Java system properties with the -D argument when starting the JVM.
  8. A Remote Function Call (RFC) with using Secure Network Communication (SNC) for encryption but without using the Single Sign On (SSO) mechanism for logon authentifaction is not possible.
  9. An RFC logon to an SAP ABAP backend system with external user identification data is not supported.
  10. An RFC logon to an SAP ABAP backend system fails with a  JCoException and the error message "Select one of the installed  languages" being thrown when using a logon language that is available in Unicode SAP systems only.
  11. The JCoDestinationMonitor interface is lacking an API for querying  the number of threads that are currently waiting for a free connection.

 

Note 1077727 contains information about supported platforms and sources say that this soon should contain Java 7 and a couple of more operating systems.

 

Java Connector is available form SAP Service Marketplace Connectors where you have to follow the embarrassing path

-> SAP Java Connector

-> Tools & Services

-> Download SAP JCo Release 3.0

(embarrassing because this is still not directly linkable in 2012...)

This is down-loadable to customers only, you need Service -Marketplace access.

Creating & Sending an IDoc to ERP using JCO 3.0 and IDoc Class Library 3.0

$
0
0

This blog will help in creating an application to send the IDoc from JAVA to ERP System.

 

JCO 3.0 & SAP IDoc Library 3.0 provides 2 ways in which the IDoc can be sent to the ERP System

  1. Sending an IDOC as IDOCDocument
    • In this the user can manually create an IDOC Document and can send it to the ERP System
  2. Creating an IDOC as XML and sending as Document List
    • In this User can generate XML and then can send the XML as IDocDocumentList

 

Prerequisite:

  • JDK/JRE 5,6,7
  • sapjco3.jar
  • sapidoc3.jar

 

sapjco3.jar & sapidoc3.jar can be downloaded from http://service.sap.com/connectors

 

If the version of Java 1.3 or 1.4 then user should use JCO 2.1. Class structure is different in that and is not covered in this blog

 

This blog provides the step by step process to send an IDOC using JCO 3.0 and Java IDOC Class Library 3.0.

 

The Class BaseIDocInboundWrapper (Step 1) & IDocInboundWrapper (Step 2) can be reused for all the IDoc Types

 

Step1. Create a Class BaseIDocInboundWrapper

Sample Class Code for BaseIDocInboundWrapper

 

package com.idoc.sender;


import java.io.File;
import java.io.FileOutputStream;
import java.util.Properties;


import com.sap.conn.idoc.IDocFactory;
import com.sap.conn.idoc.IDocRepository;
import com.sap.conn.idoc.jco.JCoIDoc;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.ext.DestinationDataProvider;


/**
 * Base Class to send the IDoc to the ERP System
 * This class creates the connection to the ERP System
 * This class also prepares to send the IDoc Files to the ERP System  
 * This Class Throws JCO Exception 
 * 
 * @author Saxena, Anish - mailto:anish.saxena@gmail.com
 *
 */
public class BaseIDocInboundWrapper {          //FIXME:READ GLOBAL ATTRIBUTES FROM PROPERTIES FILE          //Name of the Destination File          private static final String DESTINATION_NAME                     = "SampleDestination";          //Connection Attributes for SAP ERP System          private static final String JCO_AS_HOST_NAME          = "HOST_NAME";          private static final String JCO_SYSTEM_NR                = "SYSTEM_NR";           private static final String JCO_CLIENT_NR                   = "CLIENT_NR";          private static final String JCO_USER_NAME                               = "USER_NAME";          private static final String JCO_PASSWORD                               = "PASSWORD";          private static final String JCO_LANGUAGE                               = "LANGUAGE"; //EN OR DE etc...          protected static JCoDestination JCO_DESTINATION;          protected static IDocRepository IDOC_REPOSITORY;          protected static String TID;          protected static IDocFactory IDOC_FACTORY;          /**           * This method initializes the class and also connects to the ERP System            * @throws JCoException           */          public BaseIDocInboundWrapper() throws JCoException {                    connectionProperties();                    prepareERPForIDoc();          }          /**           * Create Destination Data File for the Connection           * @param l_oConnectionProperties           */          private static void createDestinationDataFile(final Properties l_oConnectionProperties){                    File destCfg = new File(DESTINATION_NAME+".jcoDestination");                     try{                              FileOutputStream fos = new FileOutputStream(destCfg, false);                               l_oConnectionProperties.store(fos, "for tests only !");                               fos.close();                    } catch (Exception e) {                              throw new RuntimeException("Unable to create the destination files", e);                    }           }          /**           * This method is initialized from the Constructor           * This method creates the connection properties file and then stores is in the default location            */          private static void connectionProperties(){                    Properties connectionProperties = new Properties();                     connectionProperties.setProperty(DestinationDataProvider.JCO_ASHOST,JCO_AS_HOST_NAME);                     connectionProperties.setProperty(DestinationDataProvider.JCO_SYSNR, JCO_SYSTEM_NR);                    connectionProperties.setProperty(DestinationDataProvider.JCO_CLIENT, JCO_CLIENT_NR);                    connectionProperties.setProperty(DestinationDataProvider.JCO_USER, JCO_USER_NAME);                    connectionProperties.setProperty(DestinationDataProvider.JCO_PASSWD, JCO_PASSWORD);                    connectionProperties.setProperty(DestinationDataProvider.JCO_LANG, JCO_LANGUAGE);                    createDestinationDataFile(connectionProperties);          }          /**           * This method is initialized from the Constructor           * This method creates the connection to the ERP System and prepares to send IDoc to ERP System           * @throws JCoException           */          private static void prepareERPForIDoc() throws JCoException{                    // get the JCo destination                    JCO_DESTINATION = JCoDestinationManager.getDestination(DESTINATION_NAME);                    // Create repository                    IDOC_REPOSITORY = JCoIDoc.getIDocRepository(JCO_DESTINATION);                    TID = JCO_DESTINATION.createTID();                    IDOC_FACTORY = JCoIDoc.getIDocFactory();          }
}

 

Step 2. Create a Class IDocInboundWrapper that will extend BaseIDocInboundWrapper created above

Sample Code for IDocInboundWrapper

 

package com.idoc.sender;


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;


import com.sap.conn.idoc.IDocDocument;
import com.sap.conn.idoc.IDocDocumentList;
import com.sap.conn.idoc.IDocFactory;
import com.sap.conn.idoc.IDocIllegalTypeException;
import com.sap.conn.idoc.IDocMetaDataUnavailableException;
import com.sap.conn.idoc.IDocParseException;
import com.sap.conn.idoc.IDocSegment;
import com.sap.conn.idoc.IDocSyntaxException;
import com.sap.conn.idoc.IDocXMLProcessor;
import com.sap.conn.idoc.jco.JCoIDoc;
import com.sap.conn.jco.JCoException;


/**
 * Class to Send the IDoc to the ERP System
 * It is a GENERIC Class for ALL Types of IDocs 
 * This class implements 2 Ways of sending IDoc to ERP System
 * Option1: Create IDoc Document and Send to ERP System. A new IDocDocument can also be fetched from this class
 * Option2: Read IDoc XML and Send to ERP System   
 * When the class is initialized connection to the ERP System is created. 
 * This Class Throws JCO Exception 
 * 
 * @author Saxena, Anish - mailto:anish.saxena@gmail.com
 *
 */
public class IDocInboundWrapper extends BaseIDocInboundWrapper{          /**           * This method initializes the class and also connects to the ERP System            * @throws JCoException           */          public IDocInboundWrapper() throws JCoException {                    super();          }          /**           * Creates an Empty IDocDocument for the connected Repository/ERP and returns the IDocDocument           * The value has to be stored in this IDocDocument             * @param p_sIDocType           * @return IDocDocument           * @throws IDocMetaDataUnavailableException           */          public IDocDocument getNewIDocDocument(String p_sIDocType) throws IDocMetaDataUnavailableException{                    IDocDocument l_oIDocDocument = IDOC_FACTORY.createIDocDocument(IDOC_REPOSITORY, p_sIDocType);                    return l_oIDocDocument;          }          /**           * This method takes the IDocDocument as the input parameter           * and sends it to the ERP System           * On Success, it returns true else throws corresponding Exception           * @see getNewIDocDocument() for getting an Empty IDoc for setting the Data.           * @param p_oIDocDocument           * @return boolean           * @throws IDocSyntaxException           * @throws IDocMetaDataUnavailableException           * @throws JCoException           */          public boolean sendIDocAsIDocDocument(IDocDocument p_oIDocDocument) throws IDocSyntaxException, IDocMetaDataUnavailableException, JCoException{                    p_oIDocDocument.checkSyntax();                    JCoIDoc.send(p_oIDocDocument, IDocFactory.IDOC_VERSION_DEFAULT, JCO_DESTINATION, TID);                       JCO_DESTINATION.confirmTID(TID);                    return true;          }          /**           * This method takes the XML Location and XML FileName as the input parameter           * Reads the XML File and sends it to the ERP System           * On Success, it returns true else throws corresponding Exception           * p_sFileName is the name of the file with the extension           * @param p_sLocation           * @param p_sFileName           * @return boolean           * @throws IOException           * @throws IDocParseException           * @throws JCoException           * @throws IDocSyntaxException           * @throws IDocMetaDataUnavailableException           */          public boolean sendIDocAsIDocXML(String p_sLocation, String p_sFileName) throws IOException, IDocParseException, JCoException, IDocSyntaxException, IDocMetaDataUnavailableException{                    String l_sIDocXML = this.readIDocXML(p_sLocation+"\\"+p_sFileName);              IDocXMLProcessor l_oIDocXMLProcessor = IDOC_FACTORY.getIDocXMLProcessor();        IDocDocumentList l_oIDocDocumentList = l_oIDocXMLProcessor.parse(IDOC_REPOSITORY, l_sIDocXML);        for(int i=0; i<l_oIDocDocumentList.size(); i++){                  IDocDocument l_oIDocDocument = l_oIDocDocumentList.get(i);                  l_oIDocDocument.checkSyntax();        }        JCoIDoc.send(l_oIDocDocumentList, IDocFactory.IDOC_VERSION_DEFAULT, JCO_DESTINATION, TID);        JCO_DESTINATION.confirmTID(TID);        return true;          }          /**           * This method takes Fully Qualified FileName along with Path as the input parameter.           * It reads the file from the Location and returns the string value of the XML           * @param p_sFullQualifiedFileName           * @return String           * @throws IOException           */          private String readIDocXML(String p_sFullQualifiedFileName) throws IOException{                    String l_sIDocXML = null;                    FileReader l_oFileReader;                    l_oFileReader = new FileReader(p_sFullQualifiedFileName);                    BufferedReader l_oBufferedReader = new BufferedReader(l_oFileReader);                    StringBuffer l_oStringBuffer = new StringBuffer();                    String l_sLine;                    while ((l_sLine = l_oBufferedReader.readLine()) != null){                              l_oStringBuffer.append(l_sLine);                    }                    l_sIDocXML = l_oStringBuffer.toString();                    l_oBufferedReader.close();                    l_oFileReader.close();                    return l_sIDocXML;          }          /**           * Main Method           * Sample Method shows how to test this class           * @param args           */          public static void main(String[] args){                    /*                     * WAY 1 SENDING AN IDOC AS IDOCDOCUMENT                     */                    try {                              IDocInboundWrapper l_oIDocInboundReceiptWrapper = new IDocInboundWrapper();                              IDocDocument l_oIDocDocument = l_oIDocInboundReceiptWrapper.getNewIDocDocument("WPUBON01");                              IDocSegment l_oIDocSegment = l_oIDocDocument.getRootSegment();                              l_oIDocSegment = l_oIDocSegment.addChild("E1WPB01");                              // and so on. User can refer the IDoc Specification for creating the IDoc Structure                              @SuppressWarnings("unused")                              boolean l_oResponse = l_oIDocInboundReceiptWrapper.sendIDocAsIDocDocument(l_oIDocDocument);                              //IF l_oResponse is true then the send was successful                    } catch (IDocIllegalTypeException oX) {                              oX.printStackTrace();                              System.out.println("An IDocIllegalTypeException has occured :: "+ oX.getMessage());                    } catch (IDocSyntaxException oX) {                              oX.printStackTrace();                              System.out.println("An IDocSyntaxException has occured :: "+ oX.getMessage());                    } catch (IDocMetaDataUnavailableException oX) {                              oX.printStackTrace();                              System.out.println("An IDocMetaDataUnavailableException has occured :: "+ oX.getMessage());                    } catch (JCoException oX) {                              oX.printStackTrace();                              System.out.println("A JCoException has occured :: "+ oX.getMessage());                    }                    /*                     * WAY 2 SENDING AN IDOC AS IDOCXML                     */                    try {                              IDocInboundWrapper l_oIDocInboundReceiptWrapper = new IDocInboundWrapper();               String l_sLocation = "C:\\Anish_Documents\\SAMPLE_IDOC_XML\\INBOUND";                              @SuppressWarnings("unused")                              boolean l_oResponse = l_oIDocInboundReceiptWrapper.sendIDocAsIDocXML(l_sLocation, "TestSalesOrder.xml");                              //IF l_oResponse is true then the send was successful                    } catch (IDocSyntaxException oX) {                              oX.printStackTrace();                              System.out.println("An IDocSyntaxException has occured :: "+ oX.getMessage());                    } catch (IDocParseException oX) {                              oX.printStackTrace();                              System.out.println("An IDocParseException has occured :: "+ oX.getMessage());                    } catch (IDocMetaDataUnavailableException oX) {                              oX.printStackTrace();                              System.out.println("An IDocMetaDataUnavailableException has occured :: "+ oX.getMessage());                    } catch (IOException oX) {                              oX.printStackTrace();                              System.out.println("An IOException has occured :: "+ oX.getMessage());                    } catch (JCoException oX) {                              oX.printStackTrace();                              System.out.println("A JCoException has occured :: "+ oX.getMessage());                    }          }

}

 

The above Step 1 and Step 2 code is generic for all the IDoc Type.

The main method in the above class demonstrates how this class can be used to send IDOC to the ERP System. There are 2 Ways in which the IDOC can be sent.

WAY 1: The user can create the custom structure of the IDOC and then can send the IDOC as IDocDocument.

WAY 2: The user can generate the XML File for the IDOC in a particular structure and then can parse the IDOC as IDocDocumentList.

 

Step 3. In this step I will be showing the WAY 2 for sending an XML File as IDOC for the IDOC Type. This step has to be performed individually for each IDOC Type

Before proceeding with this step, Create the beans with the same structure as that of IDOC Type that has to be sent to ERP System as this will be referenced in the Class that we will create in this step. The structure of the corresponding IDOC can be found by logging on ERP and with T-Code WE20.

Create a Class IDocReceiptXMLInboundWrapper

Sample Code for IDocReceiptXMLInboundWrapper for IDOC TYPE "WPUBON01" (Sales Document / Receipt)

 

package com.idoc.sender;


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;


import com.idoc.helper.EDI_DC40;
import com.idoc.helper.salesdocs.E1WPB01;
import com.idoc.helper.salesdocs.E1WPB02;
import com.idoc.helper.salesdocs.E1WPB03;
import com.idoc.helper.salesdocs.E1WPB04;
import com.idoc.helper.salesdocs.E1WPB05;
import com.idoc.helper.salesdocs.E1WPB06;
import com.idoc.helper.salesdocs.E1WPB07;
import com.idoc.helper.salesdocs.E1WXX01;
import com.idoc.helper.salesdocs.IDOC;
import com.idoc.helper.salesdocs.WPUBON01;
import com.sap.conn.idoc.IDocMetaDataUnavailableException;
import com.sap.conn.idoc.IDocParseException;
import com.sap.conn.idoc.IDocSyntaxException;
import com.sap.conn.jco.JCoException;


/**
 * Wrapper Class for Sending the Sales Docs (Receipts) to the ERP System
 * This class Creates the XML Format for the Sales Docs (Receipts)
 * It stores the XML Format and then sends the stored XML to the ERP System
 * 
 * @author Saxena, Anish - mailto:anish.saxena@gmail.com
 *
 */
public class IDocReceiptXMLInboundWrapper{
          //FIXME:READ GLOBAL ATTRIBUTES FROM PROPERTIES FILE          private static final String LOCATION = "C:\\Anish_Documents\\SAMPLE_IDOC_XML\\INBOUND";          //FIXME:REMOVE FILE_NAME AND MAKE IT DYNAMIC BASED ON RECEIPT ID OR SO          private static final String FILE_NAME = "RECEIPT_TEST.XML";           /**           * This method will create the IDoc Structure as Object           * It will internally call corresponding objects to form the IDoc Object            * @return WPUBON01           */          private WPUBON01 getWPUBON01(){                    WPUBON01 l_oWPUBON01 = new WPUBON01();                    l_oWPUBON01.setIDOC(getIDOC());                    return l_oWPUBON01;          }          /**           * @return IDOC           */          private IDOC getIDOC(){                    IDOC l_oIDOC = new IDOC();                    l_oIDOC.setBEGIN("1");                    l_oIDOC.setEDI_DC40(getEDI_DC40());                    l_oIDOC.setE1WPB01s(getE1WPB01s());                    return l_oIDOC;          }          /**           * This will return the Header Information of the IDoc as Object           * This is common for all the IDocs. Setters with setSND* can be ignored         * Direct shows its incoming or outgoing           * as it is filled when Idoc is sent from ERP.           * @return EDI_DC40           */          private EDI_DC40 getEDI_DC40(){                    EDI_DC40 l_oEDI_DC40 = new EDI_DC40();                    l_oEDI_DC40.setSEGMENT("1");                    l_oEDI_DC40.setTABNAM("EDI_DC40");                    l_oEDI_DC40.setMANDT("");                    l_oEDI_DC40.setDOCNUM("");                    l_oEDI_DC40.setDOCREL("");                    l_oEDI_DC40.setSTATUS("");                    l_oEDI_DC40.setDIRECT("");                    l_oEDI_DC40.setOUTMOD("");                    l_oEDI_DC40.setIDOCTYP("WPUBON01");                    l_oEDI_DC40.setMESTYP("WPUBON");                    l_oEDI_DC40.setSNDPOR("");                    l_oEDI_DC40.setSNDPRT("");                    l_oEDI_DC40.setSNDPRN("");                    l_oEDI_DC40.setRCVPOR("");                    l_oEDI_DC40.setRCVPRT("");                    l_oEDI_DC40.setRCVPRN("");                    l_oEDI_DC40.setCREDAT("");                    l_oEDI_DC40.setCRETIM("");                    l_oEDI_DC40.setSERIAL("");                    return l_oEDI_DC40;          }          /**           * List of Sales Documents / Receipts           * @return List<E1WPB01>           */          private List<E1WPB01> getE1WPB01s(){                    List<E1WPB01> l_oE1WPB01s = new ArrayList<E1WPB01>();                    //FIXME:ADD THE FOR LOOP HERE                    E1WPB01 l_oE1WPB01 = new E1WPB01();                     l_oE1WPB01.setSEGMENT("1");                    l_oE1WPB01.setPOSKREIS("");                    l_oE1WPB01.setKASSID("");                    l_oE1WPB01.setVORGDATUM("");                    l_oE1WPB01.setVORGZEIT("");                    l_oE1WPB01.setBONNUMMER("");                    l_oE1WPB01.setQUALKDNR("");                    l_oE1WPB01.setKUNDNR("");                    l_oE1WPB01.setKASSIERER("");                    l_oE1WPB01.setCSHNAME("");                    l_oE1WPB01.setBELEGWAERS("");                    l_oE1WPB01.setE1WPB02s(getE1WPB02());                    l_oE1WPB01.setE1WPB05s(getE1WPB05s());                    l_oE1WPB01.setE1WPB07s(getE1WPB07s());                    l_oE1WPB01.setE1WPB06s(getE1WPB06s());                    l_oE1WPB01s.add(l_oE1WPB01);                    return l_oE1WPB01s;          }          /**           * List of Materials in Receipts           * @return           */          private List<E1WPB02> getE1WPB02(){                    List<E1WPB02> l_oE1WPB02s = new ArrayList<E1WPB02>();                    //FIXME:ADD THE FOR LOOP HERE                    E1WPB02 l_oE1WPB02 = new E1WPB02();                     l_oE1WPB02.setSEGMENT("1");                    l_oE1WPB02.setVORGANGART("");                    l_oE1WPB02.setQUALARTNR("");                    l_oE1WPB02.setARTNR("");                    l_oE1WPB02.setSERIENNR("");                    l_oE1WPB02.setVORZEICHEN("-");                    l_oE1WPB02.setMENGE("");                    l_oE1WPB02.setVERKAEUFER("");                    l_oE1WPB02.setAKTIONSNR("");                    l_oE1WPB02.setREFBONNR("");                    l_oE1WPB02.setE1WPB03s(getE1WPB03s());                    l_oE1WPB02.setE1WPB04s(getE1WPB04s());                    l_oE1WPB02.setE1WXX01s(getE1WXX01s());                    l_oE1WPB02s.add(l_oE1WPB02);                    return l_oE1WPB02s;          }          /**           * Information about Material           * @return List<E1WPB03>           */          private List<E1WPB03> getE1WPB03s(){                    List<E1WPB03> l_oE1WPB03s = new ArrayList<E1WPB03>();                    //FIXME:ADD THE FOR LOOP HERE                    E1WPB03 l_oE1WPB03 = new E1WPB03();                    l_oE1WPB03.setSEGMENT("1");                    l_oE1WPB03.setVORZEICHEN("");                    l_oE1WPB03.setKONDITION("");                    l_oE1WPB03.setKONDVALUE("");                    l_oE1WPB03.setCONDID("");                    l_oE1WPB03.setCONDID20("");                    l_oE1WPB03.setQUALCONDID("");                    l_oE1WPB03.setBBYNR("");                    l_oE1WPB03s.add(l_oE1WPB03);                    return l_oE1WPB03s;           }          /**           *            * @return List<E1WPB04>           */          private List<E1WPB04> getE1WPB04s(){                    List<E1WPB04> l_oE1WPB04s = new ArrayList<E1WPB04>();                    //FIXME:ADD THE FOR LOOP HERE                    E1WPB04 l_oE1WPB04 = new E1WPB04();                    l_oE1WPB04.setSEGMENT("1");                    l_oE1WPB04.setMWSKZ("");                    l_oE1WPB04.setMWSBT("");                    l_oE1WPB04s.add(l_oE1WPB04);                    return l_oE1WPB04s;          }          /**           *            * @return List<E1WXX01>           */          private List<E1WXX01> getE1WXX01s(){                    List<E1WXX01> l_oE1WXX01s = new ArrayList<E1WXX01>();                    //FIXME:ADD THE FOR LOOP HERE                    E1WXX01 l_oE1WXX01 = new E1WXX01();                    l_oE1WXX01.setSEGMENT("1");                    l_oE1WXX01.setFLDGRP("");                    l_oE1WXX01.setFLDNAME("");                    l_oE1WXX01.setFLDVAL("");                    l_oE1WXX01s.add(l_oE1WXX01);                    return l_oE1WXX01s;          }          /**           * Discount Information           * @return List<E1WPB05>           */          private List<E1WPB05> getE1WPB05s(){                    List<E1WPB05> l_oE1WPB05s = new ArrayList<E1WPB05>();                    //FIXME:ADD THE FOR LOOP HERE                    E1WPB05 l_oE1WPB05 = new E1WPB05();                    l_oE1WPB05.setSEGMENT("1");                    l_oE1WPB05.setVORZEICHEN("");                    l_oE1WPB05.setRABATTART("");                    l_oE1WPB05.setRABSATZ("");                    l_oE1WPB05.setRABVALUE("");                    l_oE1WPB05.setCONDID("");                    l_oE1WPB05.setCONDID20("");                    l_oE1WPB05.setQUALCONDID("");                    l_oE1WPB05.setBBYNR("");                    l_oE1WPB05s.add(l_oE1WPB05);                    return l_oE1WPB05s;          }          /**           * Tax Data for Receipt           * @return List<E1WPB07>           */          private List<E1WPB07> getE1WPB07s(){                    List<E1WPB07> l_oE1WPB07s = new ArrayList<E1WPB07>();                    //FIXME:ADD THE FOR LOOP HERE                    E1WPB07 l_oE1WPB07 = new E1WPB07();                    l_oE1WPB07.setSEGMENT("1");                    l_oE1WPB07.setTAXCODE("");                    l_oE1WPB07.setTAXVALUE("");                    l_oE1WPB07s.add(l_oE1WPB07);                    return l_oE1WPB07s;          }          /**           * Payment For the Receipt           * @return List<E1WPB06>           */          private List<E1WPB06> getE1WPB06s(){                    List<E1WPB06> l_oE1WPB06s = new ArrayList<E1WPB06>();                    //FIXME:ADD THE FOR LOOP HERE                    E1WPB06 l_oE1WPB06 = new E1WPB06();                    l_oE1WPB06.setSEGMENT("1");                    l_oE1WPB06.setVORZEICHEN("");                    l_oE1WPB06.setZAHLART("");                    l_oE1WPB06.setSUMME("");                    l_oE1WPB06.setCCINS("");                    l_oE1WPB06.setWAEHRUNG("");                    l_oE1WPB06.setKARTENNR("");                    l_oE1WPB06.setKARTENFNR("");                    l_oE1WPB06.setGUELTAB("");                    l_oE1WPB06.setGUELTBIS("");                    l_oE1WPB06.setKONTOINH("");                    l_oE1WPB06.setBANKLZ("");                    l_oE1WPB06.setKONTONR("");                    l_oE1WPB06.setAUTORINR("");                    l_oE1WPB06.setTERMID("");                    l_oE1WPB06.setTRTIME("");                    l_oE1WPB06.setZUONR("");                    l_oE1WPB06.setREFERENZ1("");                    l_oE1WPB06.setREFERENZ2("");                    l_oE1WPB06.setCCBEG("");                    l_oE1WPB06.setCSOUR("");                    l_oE1WPB06.setSETTL("");                    l_oE1WPB06.setAUTRA("");                    l_oE1WPB06.setLOCID("");                    l_oE1WPB06.setREACT("");                    l_oE1WPB06.setFLGAU("");                    l_oE1WPB06.setCONDID("");                    l_oE1WPB06.setCONDID20("");                    l_oE1WPB06.setCARDGUID("");                    l_oE1WPB06.setENCTYPE("");                    l_oE1WPB06s.add(l_oE1WPB06);                    return l_oE1WPB06s;          }          /**           * Create Receipt IDoc XML and Stores it at the location with the file name           * @param p_sFileName           * @throws JAXBException           */          private void createReceiptIDocXML(String p_sFileName) throws JAXBException{                    File l_oFile = new File(LOCATION+"\\"+p_sFileName);                    JAXBContext l_oJAXBContext = JAXBContext.newInstance(WPUBON01.class);                    Marshaller l_oJAXBMarshaller = l_oJAXBContext.createMarshaller();                    l_oJAXBMarshaller.marshal(getWPUBON01(), l_oFile);                    //TO PRETTY PRINT OUTPUT                    l_oJAXBMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);                    //FIXME: TO REMOVE THIS l_oJAXBMarshaller.marshal(getWPUBON01(), System.out);                    l_oJAXBMarshaller.marshal(getWPUBON01(), System.out);          }          /**           * Send the Receipt to ERP. On Success returns true else throws exception           * @return boolean           * @throws JAXBException           * @throws JCoException           * @throws IDocSyntaxException           * @throws IDocParseException           * @throws IDocMetaDataUnavailableException           * @throws IOException           */          public boolean sendReceipt() throws JAXBException, JCoException, IDocSyntaxException, IDocParseException, IDocMetaDataUnavailableException, IOException{                    //FIXME: ADD A RECEIPT LOOP HERE                    this.createReceiptIDocXML(FILE_NAME);                    IDocInboundWrapper l_oIDocInboundReceiptWrapper = new IDocInboundWrapper();                    boolean l_oResponse = l_oIDocInboundReceiptWrapper.sendIDocAsIDocXML(LOCATION, FILE_NAME);                    return l_oResponse;          }          /**           * Main Method           * Sample Method shows how to use this class           * @param args           */          public static void main(String[] args){                    try {                              IDocReceiptXMLInboundWrapper l_oIDocReceiptXMLInboundWrapper = new IDocReceiptXMLInboundWrapper();                              boolean l_oResponse = l_oIDocReceiptXMLInboundWrapper.sendReceipt();                              if(l_oResponse)                                        System.out.println("Sales Doc (Receipt) Successfully Sent");                    } catch (IDocSyntaxException oX) {                              oX.printStackTrace();                              System.out.println("An IDocSyntaxException has occured :: "+ oX.getMessage());                    } catch (IDocParseException oX) {                              oX.printStackTrace();                              System.out.println("An IDocParseException has occured :: "+ oX.getMessage());                    } catch (IDocMetaDataUnavailableException oX) {                              oX.printStackTrace();                              System.out.println("An IDocMetaDataUnavailableException has occured :: "+ oX.getMessage());                    } catch (JAXBException oX) {                              oX.printStackTrace();                              System.out.println("A JAXBException has occured :: "+ oX.getMessage());                    } catch (JCoException oX) {                              oX.printStackTrace();                              System.out.println("A JCoException has occured :: "+ oX.getMessage());                    } catch (IOException oX) {                              oX.printStackTrace();                              System.out.println("An IOException has occured :: "+ oX.getMessage());                    }          }
}

 

Fill in the Values in the setter methods in each get... methods in the Class. This can be done by changing the method signature to accept parameters.

The main method describes how IDocReceiptXMLInboundWrapper Class can be executed. IDocReceiptXMLInboundWrapper  will internally call the classes created in Step 2 and Step 1.

 

For Converting the Object to XML, JAXB is used. 

 

After the program is executed with success message, Log in to ERP System and go to T-Code WE05. The IDoc should be visible there.

Copying file from plugin project into the local system

$
0
0

Imagine a situation where you want to copy a file from a simple eclipse plugin project into local system as soon as the eclipse workbench  opens or when the software containing the said plugin is being installed. One way to achieve this task is to use org.eclipse.ui.startup extension. This blog explains how to use this extension and to copy file from the plugin project into local system.

 

 

Eclipse plugins are loaded whenever the user needs their functionalities. This is called lazy plug-in activation. The extension org.eclipse.ui.startup is designed to break this behavior. It forces the workbench to activate the plug-in as soon as the workbench window opens. And this extension should be used only in exceptional situations as it can  affect start-up performance.

 

Note that wherever I used the term code it meant Java code.

 

Do the following steps to copy a file attached with a plugin project into the local system.

 

 

  1. Create a plugin project, say demo.startup in eclipse IDE.
  2. Make sure that you have org.eclipse.ui as dependency.
  3. Add the extension, org.eclipse.ui.IStartup.
  4. Remove the entry Bundle-ActivationPolicy: lazy from MANIFEST.MF.
  5. Attach the file, say settings.xml, which you want to copy to the project.
  6. Create a package, say demo.startup.action under src folder.
  7. Create a java class, say FileCopier.

 

The FileCopier class should implement the interface IStartup (org.eclipse.ui.IStartup) and should override the method, earlyStartup() as given below.

 

 

import org.eclipse.ui.IStartup;

 

publicclass FileCopier implements IStartup {

 

     @Override

     public void earlyStartup() {           

          <Java code to copy file into local system during start up>

     }

}

 

 

 

Note that whenever the workbench opens, the plugin is loaded immediately and  earlyStartup() method is called automatically.

 

Now open the plugin.xml file and insert your startup class name as given below.

 

 

<plugin>

   <extension

         point="org.eclipse.ui.startup">

         <startupclass="demo.startup.action.FileCopier"/>

   </extension>

</plugin>

 

 

 

Copying the file

 

Read the source  file (i.e. settings.xml) from the project

 

 

InputStream  inputStream =  this.getClass().getClassLoader().getResourceAsStream ("settings.xml");

 

 

Create a local file (i.e. target file) where you want to store the content of settings.xml.

 

 

File targetFile = new File(“C:/temp/settings.xml”);

 

 

Before copying make sure that the target file already exists. If exists check if the contents are same. If same, do not copy. Otherwise either overwrite or make a copy of existing file and then do copying. I prefer the second approach.

 

 

if(targetFile.exists()){

            InputStream targetInputStream = new FileInputStream(targetFile);

            if(contentEquals(inputStream,targetInputStream)){

                        return;

            }

            inputStream.close();

            targetInputStream.close();

            renameFile(targetFile);

            inputStream = getClass().getResourceAsStream("settings.xml");

}

            FileOutputStream outputStream;

            outputStream = new FileOutputStream(targetFile);

            byte[] buf = new byte[1024];

            int i = 0;

            while((i=inputStream.read(buf))!=-1) {

                        outputStream.write(buf, 0, i);

            }

            inputStream.close();

            outputStream.close();

 

 

 

Here is the code to check if the contents of the files are equal.

 

 

private boolean contentEquals(InputStream inputStream, InputStream targetInputStream) throws IOException {

                        if (!(inputStream instanceof BufferedInputStream)) {

                                    inputStream = new BufferedInputStream(inputStream);

                        }

                        if (!(targetInputStream instanceof BufferedInputStream)) {

                                    targetInputStream = new BufferedInputStream(targetInputStream);

                        }

                        int ch = inputStream.read();

                        while (-1 != ch) {

                                    int ch2 = targetInputStream.read();

                                    if (ch != ch2) {

                                                return false;

                                    }

                                    ch = inputStream.read();

                        }

 

                        int ch2 = targetInputStream.read();

                        return (ch2 == -1);

}

 

 

 

Here is the code to rename the existing file.

 

 

private void renameFile(File targetFile) throws IOException {

      for(int i=1;;i++){

          String newName = targetFile.getName().substring(0, targetFile.getName().lastIndexOf("."));

          newName = newName.concat(" - Copy ("+i+")"+".xml");

          File file = new File(targetFile.getParent()+File.separator+newName);

          if(file.exists()){

               continue;

         }

 

        FileInputStream inputStream = new FileInputStream(targetFile);

        FileOutputStream outputStream = new FileOutputStream(file);

        byte[] buf = new byte[1024];

        i = 0;

        while((i=inputStream.read(buf))!=-1) {

            outputStream.write(buf, 0, i);

        }

        break;

    }

}

 

 

Note: Catch the exceptions wherever required.

 

 

Restart the eclipse IDE. The file must be copied into the specified location in your local system. In case the file already exists and the content is not the same as that of the new file then it will create a copy like settings - Copy.xml. If settings – copy.xml file also exists then it will create settings - Copy (2).xml and so on.

Continuous delivery != continuous alerting

$
0
0

Continuous delivery seems to be the latest craze in the IT business and, naturally, SAP is riding the wave.

While following this process, I faced one mildly annoying caveat: if - during deployment - servers/services needed to be restarted, and if those servers/services were being monitored by some monitoring tool, lots of alerts would be continuously fired and lots of people would continuously receive emails, resulting in continuous frantic phone calls.

 

In this article I'd like to give you a brief walk-through on how I prevent this situation from recurring all the time. It would be noteworthy at this point, that the monitoring tool in question is vFabric™ Hyperic® (version 4.5.2, to be exact). But even if you're not using this, the article may serve as an inspiration since other monitoring tools offer similar interfaces as the one I used.

 

Starting out

To achieve what I set out to do, I wrote a small "tool" in Java which makes use of the Web Services API which Hyperic® offers. This allows for accessing and updating Hyperic® "inventory" (e.g. servers, services, alerts etc.). The so-called "HQApi Java API", a set of Java APIs can be downloaded from the Administration tab of the main UI. Anybody interested in the documentation will find it here.

 

For the actual build automation and deployment, we use Atlassian Bamboo®. The build plan (slightly simplified) looks like this:

Screen Shot 2012-12-09 at 19.49.46 .png

The first and last step are where the magic is performed

 

Prerequisites

The tool is written in Java, so obviously a Java Runtime Environment is required. In our case, this was a given since it is called from a remote build agent, which already requires Java. The aforementioned HQApi Java API also needs to be installed. Ensure that the path to the hqapi's lib folder and and all the JARs bundled therein as well as the conf folder (which contains a log4j.properties) are on the CLASSPATH environment variable, along with a JAR containing the tool.

Additionally, a user and password for the Hyperic® server are needed, whereby the user needs to have administrator's privileges.

 

Usage

When all the requirements have been met, you should be able to call tool. Appending the switch --help will display the possible options.

Screen Shot 2012-12-09 at 20.48.11 .png

To avoid specifying the connection parameters (host, port, user and password) each time you run the command, you might consider putting these parameters in a file client.properties. For such a file, the following locations are taken into consideration (in the given order):

  • the hqapi's conf folder
  • $HOME/.hq/ of the user making the call

 

Sample content of such a file:

 

host=hyperic.our.domain

port=7443

secure=true

user=hypericadmin

password=password4hypericadmin

 

However, the switches --action and --id (the ID of the alert which is to be activated/deactivated), are required. When in doubt, the latter can be found in the Hyperic® user interface:

hyperic.png

So, the complete call to disable an alert would be:

 

java -Dhqapi.logDir=/tmp -cp $CLASSPATH tools.hyperic.ToggleAlert --id=10631 --action=disable

 

Wrapping it all up (quite literally, actually...)

Since in my case it was  necessary to disable/enable multiple alerts, I chose to put all the steps (setting up the CLASSPATH environment variable, looping over a list of alert IDs) into two bash scripts. This simplifies the definition of the task in the build plan:

Screen Shot 2012-12-10 at 8.48.51 .png

 

So, there you have it.

One final remark: find attached the source code as *.txt (which was zipped during upload; file types *.java/*.jar are unfortunately not allowed). Modify to your heart's content


How To Avoid Sonar Violations

$
0
0

Compromising with quality will slow down productivity.  So continuous evaluation is required to check the quality of the code. Sonar does this. Sonar is a java based open source platform that evaluates and reports on source code quality. Sonar also helps Continuous Integration process. Sonar has a set of rules violating which will fail the  build.

 

Here are some Do's and Dont's that will help the developer in aviding sonar violations.

 

1. Do not throw Raw Exception Types

 

     Instead of throwing raw exception types such as Exception, Throwable or Error, throw specific exceptions.

 

2. Do not use deprecated methods

 

3. Do not use == or != operators for string comparision


     The operators == and != are used for comparing java.lang.String objects for reference equality.  Unless both strings are constants or have been interned using the String.intern() method, use equals(Object) method instead.

 

4. Do not throw exception in finally block

 

     Sonar treat this violation as very severe one.


5. Do not have empty catch block


       Empty catch block nullify the effect of throwing exception. Log the exception properly or do some relevant operations in the catch block.

 

6. Do not have empty finally Block

 

     Empty finally blocks are useless.


7. Use braces in If-else and for statements.

 

     Braces make the code highly readable.

 

8. Do not catch java.lang.Exception, java.lang.Error or java.lang.RuntimeException.

 

     Catch the specific exceptions.

 

9. Do not declare Throws Exception  in method signature

 

     Throw specific exceptions.


10. Do not write System.out.print

 

     Log the information instead of using System.out.print or System.out.println statement.

 

11. Follow naming conventions

    

     Class names should always begin with an upper case letter and method name should begin with lower case letter.

 

12.  Do not rethrow exception in catch block

 

     Catch blocks that merely rethrow a caught exception only increase the code size and runtime complexity.

Building Extensible Composite Applications with SAP [free PDF]

$
0
0
Building Extensible Composite Applications with SAP - Book Cover

A couple of years back when I started blogging on SCN I wrote a series of articles about how-to develop extensible Java applications. Inspired by the Business Add-In (BAdI) framework I even came up with a concept to provide extension points for any application running on a Java EE application server such as the SAP Composition Environment (CE).

 

Shortly after publishing those articles I was contacted by SAP Press asking me to write a whole book about it and so I did. You can read the whole story here.

 

Well, a few weeks back the book was put out of print... the good news: You can now download the PDF version for free!

 

  • [Download] You can now download the PDF version of this book free of charge! (4.4 MB)
  • [Source] Here's the source code (8.7 MB)

Note: While the book focuses on how-to develop Composites based on the SAP Composition Environment the underlying concept purely leverage standard features of Java EE and as such are definitely applicable to other application servers (with minor modifications.)

 

Matter of fact I have been thinking about porting the whole extensibility framework to the 2.x branch of SAP HANA Cloud - stay tuned! 

Basic Java security

$
0
0

For those who have ever had to work with basic JEE requirements like web service security and restrict access to business functions in EJB or WDJ applications know that this isn’t easy. It is easy to create the business logic and expose it as a web service. There are wizards in NWDS that guide you. But how do you apply security?

 

There is no step in the web service creation wizard to guide you adding a minimum authorization level. There is no wizard that lets you define UME actions needed to run a function. Finding out how to do this and putting the several development and configuration steps together is up to you, the developer. This also explains why most Java applications you find in a SAP system are not secured. Try it out: take a custom WDJ or EJB web service and see if you can call it as anonymous user. With some luck, at least the WDJ application requests an authenticated user. But only when the developer explicitly added this during design time. The flag is deactivated by default when creating a new application:

screenshot.427.jpg

The only thing a user needs to call the application is the URL. Calling a EJB from inside your Java code is not complicated and allows you to circumvent the web service part. How many developers or code reviewers actually check that the interface performs a permission check?

 

SAP has quite a reputation when it comes to security, as a matter of fact SAP employees can be proud of it in making software enterprise ready. This reputation does not only come from seeing “not authorized to run transaction xyz” all the time, but that you can make SAP pretty secure. Now, why is SAP not supporting developers a little bit more in producing secure Java software?

 

If a developer gets the task to add web service security, this means: searching for the information on SAP Help or SCN and find a not so easy to understand example. It is not easy to find permission and security best practices on SAP Help for WDJ or EJB. And the developer has to leave the IDE. As this costs time, it's outsourced to Basis: “add authentication on web service level.” IF it is taken into consideration. Letting the portal handle this is not uncommon, ignoring the fact that the direct URL to call the WDJ application is still accessible. As for using UME permissions to be able to call a business function, this means to implement the action in a new DC, add the action to a role, add the permission check in your code, etc.

 

This where wizards that guide developers to include security features directly into the application will be more than helpful. As the definitions included during design time are only one part of it, tools that ensure easy configuration of these features during runtime would be even better (DevOps). Instead of letting the developer deploy a secure application that no one can use immediately because of the added security, an automated configuration needs to be executed during deploy time.

 

Until then, just because you need to log on to the SAP Portal to run a WDJ/EJB application does not mean the application is secured.

Is Eclipse SLOWING You Down?

$
0
0

Hi All,

 

Just goto Windows-> Preferences and check the ‘Show Heap Status’ .

 

GarbageCollector.jpg

 

And press The Garbage Collector Button. Here's the before and after results.

 

Voila! ! !

 

Thanks Nick.

A Mobile PrimeFaces example based on MyFaces 2.0 running on NW 7.31

$
0
0

Hi everybody,

 

after changing our netweaver runtime platform from 7.0 to 7.31 , I spent a lot of time, trying to migrate some of our TomCat 7.0-based web-application to SAP Netweaver 7.31.

 

The most of these applications are using popular components/techniques like MyFaces 2.0 (JSF 2.0), Tomahawk, PrimeFaces, Mobile PrimeFaces, Trinidad, CDI, JPA....

 

Because of the fact that NW 7.31 still supports EE 5.0 (not EE 6.0), in most cases the SAP JSF 1.2 implemenation was insufficient for our needs.

 

After reading lots of the documents in SDN about "heavy ressource loading", I found a way to separate the MyFaces (JSF) 2.0 libraries into a library project, so that I could use the Mobile PrimeFaces components in my dynamic web projects, referencing the MyFaces 2.0 implementations via a hard class loader reference.

 

    <!-- JSF 2.0:  MyFaces 2.0.x-Implementierung -->

    <reference reference-type="hard" prepend="true">

        <reference-target provider-name="oevbs.de"

            target-type="library">myfaces~2.0.x</reference-target>

    </reference>

 

The most difficult part was to decide which jars to place in the MyFaces 2.0 library project to avoid "class not found"-runtime exceptions. But I still found a solution that fulfilled our requirements.

 

Because of the fact that there still is a big interest in using popular java techniques that exceed the possibilties of the EE 5.0 implementation on NW 7.3, I decided to post my solution in SDN.

 

The example project is a skeleton of an existing project we use in our insurance ("Elektronische Versicherungsbestätigung"). (Sorry, for the field names and comments in the project example beeing in german language).

 

If you like, you'll find all sources of the example project in the Code Exchange Repository: "https://code.sdn.sap.com/svn/MobilePrimeFacesExample/"

 

Important Notice:

  • For entering "Code Exchange", you have to be a registered user!
  • To exclude conflicts with the different licence agreements, I removed the "open source" jars from the project!

 

 

If you just want to see the running web-application:

 

  1. log in to SCN (http://scn.sap.com/community/code-exchange)
  2. download the enterprise-application-archiv "eVBMobilExampleEAR.ear" ("https://code.sdn.sap.com/svn/MobilePrimeFacesExample/eVBMobilExampleEAR/eVBMobilExampleEAR.ear")
  3. download the needed jars (See: "https://code.sdn.sap.com/svn/MobilePrimeFacesExample/eVBMobilExample/WebContent/WEB-INF/Needed_Libraries.txt" for the download-locations!)
  4. place the jars into the zipped "eVBMobilExampleEAR.ear"-file below the following lib-folder:One.jpgTwo.jpg
  5. download the library-sda-file "MyFaces20x.sda" (See: "https://code.sdn.sap.com/svn/MobilePrimeFacesExample/MyFaces20x/MyFaces20x.sda")
  6. download the needed jars (See: "https://code.sdn.sap.com/svn/MobilePrimeFacesExample/MyFaces20x/Needed_Libraries.txt" for the download-locations!)
  7. place the jars into the zipped "MyFaces20x.sda"-file below the following lib-folder (Notice: The names of the jars must exactly match to the listed names in the provider.xml) :Three.jpg
  8. deploy the standard library file: "MyFaces20x.sda" and accordingly the Enterprise Archiv: "eVBMobilExampleEAR.ear"

 

Call the web-application using the URL: "http://{Your Hostname:Port}/eVBMobilExample".

 

If everything works fine, you should see the following dialog-pages:DialogStep1.jpgDialogStep2.jpgDialogStep3.jpgDialogStep4.jpg

 

Regards

Steffen

Proxy Class to access SAP Functions: JCo and Enterprise Connector

$
0
0

Hello All,

 

This blog is a compilation of quick steps to develop proxy classes to access the SAP functions(remote-enabled) from non-SAP UI technologies.

 

[ Inspired by the forum question : http://scn.sap.com/thread/3404002 ]

 

The steps to be followed are:

 

1. Install NWDS on your local machine.

 

     NWDS is available in SDN. For complete list of NWDS versions use the link: https://nwds.sap.com/swdc/downloads/updates/netweaver/nwds/ce/ (It requires an S-User ID. Contact any SAP developer for an S-User ID).

 

2. Then, create a Java Project.

JcoConnector_1.PNG

 

3. Complete the Project creation. Right-click on project and choose New->Other. In the window select " Enterprise Connector ".

JcoConnector_2.PNG

 

4. Click Next. Then, fill the necessary fields.

JcoConnector_3.PNG

5. Provide the SAP System details and SAP login credentials to access the remote-enabled SAP functions.

JcoConnector_4.PNG

 

6. On successful login, search for the function to be used by your application i.e. function for which the proxy classes are required.

 

JcoConnector_5.PNG

 

7. Finally, the proxy classes are generated.

 

However, since the JCo library files/apis are not available in the Java project, it results in compile errors for all SAP JCo classes in the project.

 

The following steps will assist you on add the JCo related jar files to the Java project.

 

1. Go to the build path of the Java project. Choose, External Jars and navigate to the plugins folder of the NWDS.

 

2. Look up the plugins for the following jar files:

 

  • SAPmdi.jar
  • sapjco.jar
  • aii_util_msc.jar
  • aii_proxy_rt.jar

 

JcoConnector_11.PNG

3. Click on OK. Now, the java project and proxy classes are ready to be used in your application.

 

All the Best.

 

Regards,

Sharath

Deploy SAP Java applications

$
0
0

To deploy a SAP Java application like Web Dynpro Java or SAP Portal application, tools like NWDS, NWDI or telnet are used. This is a very SAP centric setup. But how can you deploy a WDJ application without using NWDI, NWDS, telnet or direct server access? What if you want to deploy it out of your continuous integration (CI) server?

 

EAR, SDA, WAR, PAR, SCA?

 

First question to ask and to answer is: what file can be deployed? Normally, SAP Java applications are in SCA or SDA format. Standalone WDJ applications are EAR and portal files are SDA. The good news is that they are ZIP files. The portal SDA is basically the old PAR file renamed to SDA and WDJ EAR files are … EAR files. NWDS will create the files correctly, it’s just picking these files up – or create them manually - and deploy them to NW Java.

 

Note for WDJ EAR and SDA transformation

On releases 7.1 and higher, .EAR files are automatically converted to SDA format during deployment. [SAP Note 1715441 - How to deploy .SDA / .EAR files on J2EE servers on Netweaver release 7.1 and higher]

 

The tools

 

In NWDS 7.1 versions there was a folder with ant scripts provided.http://help.sap.com/saphelp_nwce711/helpdata/en/46/150746f21914dce10000000a155369/content.htm

deploy1.jpg

This folder and therefore the tools are gone in newer NWDS versions. Basically, there are no client side tools provided by SAP to deploy an application without using a SAP tool. The SAP Note 1715441 contains all the information regarding on how to deploy an application. It contains one entry about a deployment script:

 

Using filesystem deployment script

  • Open the "deployment script" folder located in /usr/sap/<SID>/J<nr>/j2ee/deployment/scripts.
  • Run the command "deploy.bat <user>:<password>@<host>:<port> <archive location>"  (For example on a windows server, run "deploy.bat hemadm:initial1d@pwdf3341:50004 C:\testsda.sda"

 

Taking a look at the mentioned deployment directory unveils:

deploy2.jpg

There is an ant directory with an example ant build file. You can take this script and try it out to see if it matches your needs. In my case it didn’t. The SAP Note mentions a script directory; let’s take a look at it:

deploy3.jpg

Running the deploy.csh script shows the application help.

deploy4.jpg

Doing a deploy from the cmd line on the server:

deploy5.jpg

Great, it works! But only from the server. What about freedom and deploy WDJ / Portal applications from your CI?

 

Java version

 

A look inside the file reveals that deploy.csh is a wrapper for calling a Java application. To be able to trigger a deploy from anywhere you want, all it takes is a Java application with the required JAR files. All the JAR files can be found in the deployment dir:

  • /usr/sap/<SID>/J<nr>/j2ee/deployment
  • /usr/sap/<SID>/J<nr>/j2ee/j2eeclient

 

The JAR files are:

 

  • lib/javaee_deployment-1_2-fr-class.jar
  • lib/sap.com~tc~je~deployment14~impl.jar
  • /lib/ant.jar
  • /lib/sap.com~tc~bl~jarsap~impl.jar
  • /lib/sap.com~tc~sapxmltoolkit~sapxmltoolkit.jar
  • /lib/sap.com~tc~bl~sl~utility~impl.jar
  • /lib/sap.com~tc~je~adminadapter~impl.jar
  • /lib/deploy_lib~sda.jar
  • /j2eeclient/sap.com~tc~je~clientlib~impl.jar
  • /j2eeclient/sap.com~tc~logging~java~impl.jar
  • /j2eeclient/sap.com~tc~exception~impl.jar

 

The Java class to call is

  • com.sap.engine.deployment.DMClient

 

Copy these files to a lib directory on the computer from where the deploy will be done. The command to do a deploy of a custom EAR file from command line using Java is:


java.exe -Dserver.parser.inqmy=true -Dproxy=DC -classpath ".;lib/javaee_deployment-1_2-fr-class.jar;lib/sap.com~tc~je~deployment14~impl.jar;lib/ant.jar;lib/sap.com~tc~bl~jarsap~impl.jar;lib/sap.com~tc~sapxmltoolkit~sapxmltoolkit.jar;lib/sap.com~tc~bl~sl~utility~impl.jar;lib/sap.com~tc~je~adminadapter~impl.jar;lib/sap.com~tc~je~clientlib~impl.jar;lib/sap.com~tc~logging~java~impl.jar;lib/sap.com~tc~exception~impl.jar;lib/deploy_lib~sda.jar" com.sap.engine.deployment.DMClient tobias:<password>@nwce73:50004 ./demo.sap.com~tobias~blog~ear.ear

 

All the JAR files are in one common lib directory and the name of the ear file is demo.sap.com~tobias~blog~ear.ear.

The deploy application expects a certain files and folders structure that is given on the server, but not on the client. My deploy folder looks like:\

deploy6.jpg

  • lib-> JAR files, resolved by ivy
  • deployment/cfg -> contains one of the config files
  • a, b and the rest is created dynamically by the deploy application.

 

Continuous integration

 

The above Java call can be converted easily into a (ant) script. As such, it is also very easy to integrate into a CI server like Jenkins. There are five parameters that have to be set:

  • username
  • password
  • server
  • port
  • file to deploy

In Jenkins this is done inside the job configuration by checking “This build is parameterized” and adding parameters:

deploy7.jpg

This gives the option to build the job with parameters:

deploy8.jpg

deploy9.jpg

Inside build.xml these parameters can be referenced using:

<arg value="${env.NWUser}:${env.NWPassword}@${env.NWServer}:${env.NWPort}"/>

 

This allows to deploy a EAR, SDA file out of your CI server. After a build the application can be deployed and the functional / load test can be run and integrated into the overall CI job run result. Transparency for your SAP Java projects.

 

Remark

 

A problem is – unfortunately – that the Java program does always return a successful execution as long as the application does not hit an error in the execution flow; like: logon not possible, missing EAR file. When the deploy returns an error, the application still returns success to the ant task, as the execution steps of the deploy application worked. To report a build failure on a failed server side deploy you’ll have to check the logs.


Java Tutorial HastSet, HashMap (PART 4)

$
0
0

 

This tutorial present how to use the HashMap and the HashSet Collections and also that yuo need to override the equals and to implement the Comparable interface if you use the Set interface and the hashCode method if you use the Hash interface. Also the static block is presented.

Playing with JCo3

$
0
0

So I downloaded the Java connector sapjco3.jar and the examples and started to play.

I soon got put off by the fact that all the examples require a username and password to be stored in a file and the idoc example I found was a bit over complicated for someone coming from an ABAP background.

 

Much Googling later and here is what I ended up with. This stores the system connection details in a file but NOT the username and password.

The idoc is created by calling a RFC function and the bit that casts a JCoStructure into a String (to populate the sdata field) is quite useful (I think).

 

--------- Start Java Code --------------
import java.util.HashMap;
import java.util.Properties;
import java.io.FileInputStream;
import java.io.IOException;

import com.sap.conn.jco.*;
import com.sap.conn.jco.rt.*;
import com.sap.conn.jco.ext.*;

/**
* This is the example that SAP should have delivered It keeps the system name
* etc in a file but not the user and password
*
* It will call a RFC function to create an idoc and print out the returned data
*
* Create a file called ABAP_AS.jcoDestination as below
* jco.client.lang=<language>
* jco.client.client=<client>
* jco.client.sysnr=<system number>
* jco.client.ashost=<hostname>
*
* Enter the required values starting lines: 158,185,196

* Install sapjco3,

* set environment variables: classpath, lib_path and path

* Compile with : javac iDocTest.java

* Run with command java iDocTest
*/
public class iDocTest {

    static String ABAP_AS = "ABAP_AS";

    static class MyDestinationDataProvider implements DestinationDataProvider {

        private DestinationDataEventListener eL;
        private HashMap<String, Properties> secureDBStorage = new HashMap<String, Properties>();

        public Properties getDestinationProperties(String destinationName) {
            try {
                //read the destination from DB
                Properties p = secureDBStorage.get(destinationName);

                if (p != null) {
                    //check if all is correct, for example
                    if (p.isEmpty()) {
                        throw new DataProviderException(DataProviderException.Reason.INVALID_CONFIGURATION, "destination configuration is incorrect", null);
                    }

                    return p;
                }

                return null;
            } catch (RuntimeException re) {
                throw new DataProviderException(DataProviderException.Reason.INTERNAL_ERROR, re);
            }
        }

        //An implementation supporting events has to retain the eventListener instance provided
        //by the JCo runtime. This listener instance shall be used to notify the JCo runtime
        //about all changes in destination configurations.
        public void setDestinationDataEventListener(DestinationDataEventListener eventListener) {
            this.eL = eventListener;
        }

        public boolean supportsEvents() {
            return true;
        }

        //implementation that saves the properties in a very secure way
        void changeProperties(String destName, Properties properties) {
            synchronized (secureDBStorage) {
                if (properties == null) {
                    if (secureDBStorage.remove(destName) != null) {
                        eL.deleted(destName);
                    }
                } else {
                    secureDBStorage.put(destName, properties);
                    eL.updated(destName); // create or updated
                }
            }
        }
    } // end of MyDestinationDataProvider

    static Properties getDestinationPropertiesFromUI() {

        Properties userProperties;
        Properties sapProperties;
        String JCO_CLIENT;
        String JCO_LANG;
        String JCO_SYSNR;
        String JCO_HOST;

        sapProperties = new Properties();
        userProperties = new Properties();

// Load ABAP_AS.jcoDestination file
        try {
            sapProperties.load(new FileInputStream("ABAP_AS.jcoDestination"));

        } catch (IOException ex) {
            ex.printStackTrace();
        }
        // Get fixed connection details from properties file 
        JCO_LANG = sapProperties.getProperty("jco.client.lang");
        JCO_HOST = sapProperties.getProperty("jco.client.ashost");
        JCO_SYSNR = sapProperties.getProperty("jco.client.sysnr");
        JCO_CLIENT = sapProperties.getProperty("jco.client.client");
// Set connection details from strings retrieved fromn file above           
        userProperties.setProperty(DestinationDataProvider.JCO_ASHOST, JCO_HOST);
        userProperties.setProperty(DestinationDataProvider.JCO_SYSNR, JCO_SYSNR);
        userProperties.setProperty(DestinationDataProvider.JCO_CLIENT, JCO_CLIENT);
        userProperties.setProperty(DestinationDataProvider.JCO_LANG, JCO_LANG);

// Get username and password 
        System.console().printf("Enter user:");
        userProperties.setProperty(DestinationDataProvider.JCO_USER, System.console().readLine());

        System.console().printf("Enter password:");
        userProperties.setProperty(DestinationDataProvider.JCO_PASSWD, System.console().readLine());


        return userProperties;

    }

    public static void iDocCall(String destName) throws JCoException {
        //Declare destination for function call
        JCoDestination destination = JCoDestinationManager.getDestination(destName);
        String client = destination.getClient();

        // Declare function and check it exists
        JCoFunction idoc_input = destination.getRepository().getFunction("IDOC_INBOUND_SINGLE");
        if (idoc_input == null) {
            throw new RuntimeException("IDOC_INBOUND_SINGLE not found in SAP.");
        }

// Declare function fields, structures and tables
//JCoFunction is container for function values. Each function contains separate
//containers for import, export, changing and table parameters.
//To set or get the parameters use the APIS setValue() and getXXX().   

// Declare:       
// Import Fields   
//      idoc_input.getImportParameterList().setValue("MASS_PROCESSING", " ");

// Structures
        JCoStructure idoc_control = idoc_input.getImportParameterList().getStructure("PI_IDOC_CONTROL_REC_40");

//Tables       
        JCoTable idoc_data = idoc_input.getTableParameterList().getTable("PT_IDOC_DATA_RECORDS_40");

// Populate function fields, structures and tables     
// To create the idoc we only need to set the control and data
//iDoc Control
        idoc_control.setValue("MANDT", client);
        idoc_control.setValue("DIRECT", "2");
        idoc_control.setValue("MESTYP", "MBGMCR");
        idoc_control.setValue("IDOCTYP", "MBGMCR02");
        idoc_control.setValue("CIMTYP", "ZMBGMCR02001");
        idoc_control.setValue("SNDPOR", <enter_sndpor>);
        idoc_control.setValue("SNDPRT", <enter_sndprt>);
        idoc_control.setValue("SNDPRN", <enter_sndprn>);
        idoc_control.setValue("RCVPOR", <enter_rcvpor>);
        idoc_control.setValue("RCVPRT", <enter_rcvprt>);
        idoc_control.setValue("RCVPRN", <enter_rcvprn>);

//iDoc Data           
        JCoRepository repository = destination.getRepository();
        JCoStructure str_head, str_item;
        JCoRecordMetaData meta_head, meta_item;
        String sdata = "";

//Create structures for sdata population
        meta_head = repository.getStructureDefinition("E1BP2017_GM_HEAD_01");
        str_head = JCo.createStructure(meta_head);

        meta_item = repository.getStructureDefinition("E1BP2017_GM_ITEM_CREATE");
        str_item = JCo.createStructure(meta_item);

        // Write idoc data
        idoc_data.appendRows(2); // Add 4 rows to internal table
        idoc_data.setValue("MANDT", client);
        idoc_data.setValue("SEGNUM", "1");
        idoc_data.setValue("PSGNUM", "0");
        idoc_data.setValue("SEGNAM", "E1BP2017_GM_HEAD_01");

        str_head.setValue("HEADER_TXT", "Java test");
        str_head.setValue("PSTNG_DATE", "20131008");
        str_head.setValue("REF_DOC_NO", "12345");
        sdata = ConvertToSDATA(str_head, meta_head);
        idoc_data.setValue("SDATA", sdata);

        idoc_data.nextRow(); // Move to next row
        idoc_data.setValue("MANDT", client);
        idoc_data.setValue("SEGNUM", "2");
        idoc_data.setValue("PSGNUM", "0");
        idoc_data.setValue("SEGNAM", "E1BP2017_GM_ITEM_CREATE");
        str_item.setValue("MATERIAL", <enter_material>);
        str_item.setValue("BATCH", <enter_batch>);
        str_item.setValue("ENTRY_QNT", <enter_qty>);
        str_item.setValue("EXPIRYDATE", <enter_sled_date>);
        sdata = ConvertToSDATA(str_item, meta_item);
        idoc_data.setValue("SDATA", sdata);

 

//To set or get the parameters use the APIS setValue() and getValue(). 
        idoc_input.getTableParameterList().setValue("PT_IDOC_DATA_RECORDS_40", idoc_data);

// Execute the function call
        try {
            idoc_input.execute(destination);
        } catch (AbapException e) {
            System.out.println(e.toString());
            return;
        }

        // Get returned idoc number
        String idoc_number;
        idoc_number = idoc_input.getExportParameterList().getString("PE_IDOC_NUMBER");

        // Remove leading zeros from idoc number
        idoc_number = idoc_number.replaceFirst("^0*", "");
        if (idoc_number.isEmpty()) {
            idoc_number = "0";
        }
        // Write out idoc number
        System.out.println("Created idoc number " + idoc_number);

    }

    public static String ConvertToSDATA(JCoStructure data_in, JCoRecordMetaData meta_in) {
        /*
        Simply casting the structure to a string will fail (won't compile)
        Concatenating the structure fields into a string will remove all the spaces
        so the field alignment is lost.
        The solution is to create a StringBuilder object of the correct length
        Initialize it with all spaces and then, using the structure metadata,
        insert each field at the correct start position
        * NB: This works for idocs where all fields are character types
        */
        String sdata = "";
        int count = 0;
        int Start = 0;
        int End = 0;
        int Len = 0;

        // Declare string builder as 1000 long and fill with spaces
        StringBuilder strB = new StringBuilder(" ");
        strB.setLength(1000);
        ClearString1000(strB, 1000);

        // Get field count in structure
        count = meta_in.getFieldCount();
        count = count - 1;

        for (int i = 0; i <= count; i++) {
            Len = meta_in.getLength(i);
            End = Start + Len;
            strB.insert(Start, data_in.getValue(i));
            Start = End++;
        }
        sdata = strB.toString();
        return sdata;
    }

    public static StringBuilder ClearString1000(StringBuilder str, int Len) {
        // Sets all characters to space
        for (int i = 1; i <= Len; i++) {
            str.insert(i, " ");
        }
        return str;
    }

    public static void main(String[] args) throws JCoException {

        MyDestinationDataProvider myProvider = new MyDestinationDataProvider();

        //register the provider with the JCo environment;
        //catch IllegalStateException if an instance is already registered
        try {
            com.sap.conn.jco.ext.Environment.registerDestinationDataProvider(myProvider);
        } catch (IllegalStateException providerAlreadyRegisteredException) {
            //somebody else registered its implementation,
            //stop the execution
            throw new Error(providerAlreadyRegisteredException);
        }

        String destName = "ABAP_AS";
        iDocTest dest;

        dest = new iDocTest();

        //set properties for the destination and ...
        myProvider.changeProperties(destName, getDestinationPropertiesFromUI());

        //... work with it             
        iDocTest.iDocCall(destName);

        //Clear the properties and ...
        myProvider.changeProperties(destName, null);
    }
}

--------- End Java Code --------------

ABAP Enigma Machine

$
0
0

I got interested in the story of the Enigma machines and Bletchly Park and ended up writing this, just for kicks

Now, is someone can write something in ABAP to decypher Enigma messages, please let me know.

 

*&---------------------------------------------------------------------*
*  Report  Z_ENIGMA
*
*&---------------------------------------------------------------------*
* This is a3 wheel Enigma coding machine emulator using genuine wheel settings.
* Sequence is this :-
* Input -> Plugboard -> Wheel 3,2,1 -> Reflector -> Wheel 1,2,3 -> Plugboard -> Output
*
* The plugboard is a set of connections between the wheel input and either
* the keyboard (i/P) or lightboard (o/p)
*
* An enigma wheel has a set of 26 i/p connections and 26 o/p connections
* It has a ring around the outside so these connections can be
* shifted relative to the characters that are displayed on its outer edge.
* It has a turnover point where the next wheel in the set moves 1 position
* (think how a car odometer works when it moves from 9 to 10)
*
* When in use, the initial settings have to be known by the receiving machine
* So the initial settings are encoded using some other method and transmitted
* to the receiver first. This is called public key encryption, because the key
* is known publicly (but not how to use it).
*&---------------------------------------------------------------------*
* Text symbols are defined as :
* 001 = "Enigma Settings: Wheel order, start positions and plugboard"
* 002 = "Text to be encrypted / decrypted. Characters A to Z only. No puncuation / numbers."
*
* Selection Texts are defined as :
* INIT1    = "Initial Position Wheel 1"
* INIT2    = "Initial Position Wheel 2"
* INIT3    = "Initial Position Wheel 3"
* P_PLUGB  = "Use plugboard mapping?"
* W1      = "Wheel 1"
* W2      = "Wheel 2"
* W3      = "Wheel 3"
*&---------------------------------------------------------------------*

REPORT  z_enigma .

CONSTANTS:
           c_ref_b    TYPE char26 VALUE 'YRUHQSLDPXNGOKMIEBFZCWVJAT',
           c_plugb    TYPE char26 VALUE 'ZBCDEFHGIJKLNMOPQRSTUVWXYA',
           c_alpha    TYPE char26 VALUE 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
           c_wheel1   TYPE char26 VALUE 'EKMFLGDQVZNTOWYHXUSPAIBRCJ',
           c_wheel2   TYPE char26 VALUE 'AJDKSIRUXBLHWTMCQGZNPYFVOE',
           c_wheel3   TYPE char26 VALUE 'BDFHJLCPRTXVZNYEIWGAKMUSQO',
           c_wheel4   TYPE char26 VALUE 'ESOVPZJAYQUIRHXLNFTGKDCMWB',
           c_wheel5   TYPE char26 VALUE 'VZBRGITYUPSDNHLXAWMJQOFECK',
           c_wheel6   TYPE char26 VALUE 'JPGVOUMFYQBENHZRDKASXLICTW',
           c_wheel7   TYPE char26 VALUE 'NZJHGRCXMYSWBOUFAIVLPEKQDT',
           c_wheel8   TYPE char26 VALUE 'FKQHTLXOCBJSPDZRAMEWNIUYGV',
           c_turn1    TYPE char1  VALUE 'R',
           c_turn2    TYPE char1  VALUE 'F',
           c_turn3    TYPE char1  VALUE 'W',
           c_turn4    TYPE char1  VALUE 'K',
           c_turn5    TYPE char1  VALUE 'A',
           c_turn6    TYPE char2  VALUE 'AN', "Getting sneaky by using 2 turnover positions
           c_turn7    TYPE char2  VALUE 'AN',
           c_turn8    TYPE char2  VALUE 'AN'.

DATA: v_output TYPE string,
      v_source TYPE string,
      v_temp   TYPE string,
      v_length TYPE i,
      source   TYPE string,
      wheel3   TYPE char26,
      wheel2   TYPE char26,
      wheel1   TYPE char26,
      alpha    TYPE char26,
      turn1    TYPE char1,
      turn2    TYPE char1,
      fname    TYPE char8.

TYPES : BEGIN OF ty_wrd ,
         text TYPE char80 ,
       END OF ty_wrd .

DATA: char_in    TYPE char1,
      c1    TYPE char1,
      idx   TYPE i,
      pos   TYPE i,
      char_out TYPE char1,
      lt_text  TYPE TABLE OF ty_wrd WITH HEADER LINE,
      gc_docking        TYPE REF TO cl_gui_docking_container,
      gc_text_editor    TYPE REF TO cl_gui_textedit,
      gt_text           TYPE TABLE OF tline-tdline,
      gs_text           TYPE tline-tdline.

FIELD-SYMBOLS <data> TYPE any.

*======================================================================*
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
* Choose 3 wheels
PARAMETERS: w1 TYPE ddtabind DEFAULT 1,
            w2 TYPE ddtabind DEFAULT 2,
            w3 TYPE ddtabind DEFAULT 3.
SELECTION-SCREEN SKIP 1.

* Set wheel start position
PARAMETERS: init1 TYPE sf_char1 DEFAULT 'M',
            init2 TYPE sf_char1 DEFAULT 'C',
            init3 TYPE sf_char1 DEFAULT 'K'.

SELECTION-SCREEN SKIP 1.
PARAMETERS: p_plugb AS CHECKBOX DEFAULT 'X'.

SELECTION-SCREEN END OF BLOCK b1.

SELECTION-SCREEN SKIP 2.
SELECTION-SCREEN COMMENT /1(82) text-002.


*======================================================================*
INITIALIZATION.
  PERFORM initialization.

*======================================================================*
AT SELECTION-SCREEN OUTPUT.
  TRANSLATE init1 TO UPPER CASE.
  TRANSLATE init2 TO UPPER CASE.
  TRANSLATE init3 TO UPPER CASE.

AT SELECTION-SCREEN ON BLOCK b1.
  IF w1 IS INITIAL OR
     w2 IS INITIAL OR
     w3 IS INITIAL OR
     w1 > 8 OR w2 > 8 OR w3 > 8.
    MESSAGE s001(00) WITH 'Select 3 wheel numbers from 1 to 8'.
  ENDIF.

  IF w3 = w2 OR
     w3 = w1 OR
     w2 = w1.
    MESSAGE s001(00) WITH 'Wheels cannot be used in more that 1 position'.
  ENDIF.

  IF init1 IS INITIAL OR
     init1 NA sy-abcde.
    MESSAGE s001(00) WITH 'Set start position wheel 1 A to Z'.
  ENDIF.
  IF init2 IS INITIAL OR
     init2 NA sy-abcde.
    MESSAGE s001(00) WITH 'Set start position wheel 2 A to Z'.
  ENDIF.
  IF init3 IS INITIAL OR
     init3 NA sy-abcde.
    MESSAGE s001(00) WITH 'Set start position wheel 3 A to Z'.
  ENDIF.

*======================================================================*
START-OF-SELECTION.

* Load selected wheels into work areas
  CONCATENATE 'C_WHEEL' w1 INTO fname.
  ASSIGN  (fname) TO <data>.
  wheel1 = <data>.

  CONCATENATE 'C_WHEEL' w2 INTO fname.
  ASSIGN  (fname) TO <data>.
  wheel2 = <data>.
  CONCATENATE 'C_TURN' w2 INTO fname.
  ASSIGN  (fname) TO <data>.
  turn1 = <data>.


  CONCATENATE 'C_WHEEL' w3 INTO fname.
  ASSIGN  (fname) TO <data>.
  wheel3 = <data>.
  CONCATENATE 'C_TURN' w3 INTO fname.
  ASSIGN  (fname) TO <data>.
  turn2 = <data>.

  PERFORM enigma.

*======================================================================*
FORM initialization.

* Add free text box to selection screen
  CREATE OBJECT gc_docking
    EXPORTING
      repid     = sy-repid
      dynnr     = sy-dynnr
      side      = gc_docking->dock_at_bottom
      extension = 200.

  CREATE OBJECT gc_text_editor
    EXPORTING
      parent = gc_docking.

  IMPORT gt_text FROM MEMORY ID sy-repid.
* Put in sample text
  IF gt_text IS INITIAL.
    gs_text =  'ZKA NTCKV KOGZE WAO UPHZX HZSY YNI FKMB AFP'.
* Using wheels 123 at MCK with plugboard turned on
* this will decypher to "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG"
    APPEND gs_text TO gt_text.
  ENDIF.

  CALL METHOD gc_text_editor->set_text_as_r3table
    EXPORTING
      table  = gt_text
    EXCEPTIONS
      OTHERS = 1.

ENDFORM.                    " INITIALIZATION
*&---------------------------------------------------------------------*
*&      Form  enigma
*&---------------------------------------------------------------------*
FORM enigma.

* Get text from selection screen screen editor
  REFRESH gt_text.
  CALL METHOD gc_text_editor->get_text_as_r3table
    IMPORTING
      table  = gt_text
    EXCEPTIONS
      OTHERS = 1.

  CALL FUNCTION 'CONVERT_TABLE_TO_STRING'
    EXPORTING
      i_tabline_length = 132
    IMPORTING
      e_string         = source
    TABLES
      it_table         = gt_text.

* Shift to upper case and remove all spaces
  TRANSLATE source TO UPPER CASE.
  v_source = source.
  CONDENSE source NO-GAPS.
  v_length = strlen( source ).

* Order is this :-
* Input -> Plugboard -> Wheel 3,2,1 -> Reflector -> Wheel 1,2,3 -> Plugboard -> Output
  CLEAR : v_temp, v_output.

  DO v_length TIMES.

* get input character from keyboard
    pos = sy-index - 1.
    char_in = source+pos(1).

* Validate only alphabetic characters used
    IF char_in NA sy-abcde.
      MESSAGE s001(00) WITH 'Only letters A to Z allowed'.
      LEAVE LIST-PROCESSING.
    ENDIF.

* Plugboard mapping inbound
    PERFORM plugboard USING 'I' CHANGING char_in.

* Wheel 3
* Wheel 3 always steps on 1 position before encoding starts
    CLEAR pos.
    SEARCH c_alpha FOR init3.
    pos = sy-fdpos + 1. "11
    PERFORM index_wrap CHANGING pos.
    init3 = c_alpha+pos(1).

* Setup wheel
    CONCATENATE 'C_WHEEL' w3 INTO fname.
    ASSIGN  (fname) TO <data>.
    PERFORM set_wheel USING  <data>
                             init3
                    CHANGING wheel3.

* Look for index of entered character
    SEARCH c_alpha FOR char_in.

* Get wheel character.
    c1 = wheel3+sy-fdpos(1).

* Look for index of o/p character
    PERFORM set_wheel USING  c_alpha
                         init3
                CHANGING alpha.
    SEARCH alpha FOR c1.
    idx = sy-fdpos.

* Wheel 2 turnover
    IF turn1 CA init3.
      CLEAR pos.
      SEARCH c_alpha FOR init2.
      pos = sy-fdpos + 1.
      PERFORM index_wrap CHANGING pos.
      init2 = c_alpha+pos(1).
    ENDIF.

* Wheel 2
* Setup wheel
    CONCATENATE 'C_WHEEL' w2 INTO fname.
    ASSIGN  (fname) TO <data>.
    PERFORM set_wheel USING  <data>
                             init2
                    CHANGING wheel2.

    c1 = wheel2+idx(1).

* Look for index of o/p character
    PERFORM set_wheel USING  c_alpha
                         init2
                CHANGING wheel2.
    SEARCH wheel2 FOR c1.
    idx = sy-fdpos.


* Wheel 1 turnover
    IF turn2 CA init2.
      CLEAR pos.
      SEARCH c_alpha FOR init1.
      pos = sy-fdpos + 1.
      PERFORM index_wrap CHANGING pos.
      init1 = c_alpha+pos(1).
    ENDIF.

* Wheel 1
* Setup wheel
    CONCATENATE 'C_WHEEL' w1 INTO fname.
    ASSIGN  (fname) TO <data>.
    PERFORM set_wheel USING  <data>
                             init1
                    CHANGING wheel1.

    c1 = wheel1+idx(1).

* Look for index of o/p character
    PERFORM set_wheel USING  c_alpha
                         init1
                CHANGING wheel1.
    SEARCH wheel1 FOR c1.
    idx = sy-fdpos.
    c1 = c_alpha+idx(1).

* Reflector
    SEARCH c_ref_b FOR c1.
    c1 = c_alpha+sy-fdpos(1).
    idx = sy-fdpos.

* wheel 1 again
    PERFORM set_wheel USING  c_alpha
                      init1
             CHANGING wheel1.
    c1 = wheel1+idx(1).

    CONCATENATE 'C_WHEEL' w1 INTO fname.
    ASSIGN  (fname) TO <data>.
    PERFORM set_wheel USING  <data>
                             init1
                    CHANGING wheel1.
    SEARCH wheel1 FOR c1.
    idx = sy-fdpos.

* wheel 2 again
    PERFORM set_wheel USING  c_alpha
                      init2
             CHANGING wheel2.
    c1 = wheel2+idx(1).

    CONCATENATE 'C_WHEEL' w2 INTO fname.
    ASSIGN  (fname) TO <data>.
    PERFORM set_wheel USING  <data>
                             init2
                    CHANGING wheel2.
    SEARCH wheel2 FOR c1.
    idx = sy-fdpos.

* wheel 3 again
    PERFORM set_wheel USING  c_alpha
                      init3
             CHANGING wheel3.
    c1 = wheel3+idx(1).

    CONCATENATE 'C_WHEEL' w3 INTO fname.
    ASSIGN  (fname) TO <data>.
    PERFORM set_wheel USING  <data>
                             init3
                    CHANGING wheel3.
    SEARCH wheel3 FOR c1.
    idx = sy-fdpos.

    char_out = c_alpha+idx(1).

* Plugboard mapping outbound
    PERFORM plugboard USING 'O' CHANGING char_out.

* Build output string
    CONCATENATE v_temp char_out INTO v_temp.
  ENDDO.

* Put spaces back in same place as in selection screen text
  SHIFT v_source LEFT DELETING LEADING space.
  v_length = strlen( v_source ).
  CLEAR: pos, idx.

  DO v_length TIMES.
* get selection screen character
    c1 = v_source+pos(1).

    IF c1 IS INITIAL.
      CONCATENATE v_output ' ' INTO v_output RESPECTING BLANKS.
      idx = idx + 1.
      pos = pos + 1.
      CONTINUE.
    ELSE.
      sy-fdpos = pos - idx.
      c1 = v_temp+sy-fdpos(1).
      CONCATENATE v_output c1 INTO v_output.
      pos = pos + 1.
    ENDIF.

  ENDDO.


* Write source to result screen
  REFRESH lt_text.
  CALL FUNCTION 'CONVERT_STRING_TO_TABLE'
    EXPORTING
      i_string         = v_source
      i_tabline_length = 80
    TABLES
      et_table         = lt_text.

  FORMAT INTENSIFIED ON.
  WRITE / 'Input text.'.
  FORMAT INTENSIFIED OFF.
  LOOP AT lt_text.
    SHIFT lt_text-text LEFT DELETING LEADING space.
    WRITE / lt_text-text.
  ENDLOOP.

* Write result to result screen
  REFRESH lt_text.
  CALL FUNCTION 'CONVERT_STRING_TO_TABLE'
    EXPORTING
      i_string         = v_output
      i_tabline_length = 80
    TABLES
      et_table         = lt_text.
  WRITE /.
  FORMAT INTENSIFIED ON.
  WRITE / 'Output text.'.
  FORMAT INTENSIFIED OFF.
  LOOP AT lt_text.
    SHIFT lt_text-text LEFT DELETING LEADING space.
    WRITE / lt_text-text.
  ENDLOOP.

  WRITE /.
  FORMAT INTENSIFIED ON.
  WRITE / 'If you copy the output text and use that as the input text'.
  WRITE / 'with the same initial setup on the selection screen.'.
  WRITE / 'your output will be deciphered or enciphered as required'.

ENDFORM.                    "enigma
*&---------------------------------------------------------------------*
*&      Form  plugboard
*&---------------------------------------------------------------------*
FORM plugboard USING p_direction TYPE char1
               CHANGING p_char TYPE char1.
* This is a simple x to y type mapping
*  Not all charcaters have to be mapped
* EG. You could leave everything as it comes out of the wheels
* except, say, mapping A to G (and therefore G to A)
*
* The default in this pgm only map A/Z and G/H in the plugboard
* c_alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
* c_plugb = 'ZBCDEFHGIJKLNMOPQRSTUVWXYA',
*            ^     ^^                 ^

  CHECK p_plugb = 'X'. " is plugboard mapping ON

  IF p_direction = 'I'.
* Input from keyboard to wheels
    SEARCH c_alpha FOR p_char.
    p_char = c_plugb+sy-fdpos(1).
  ELSE.
* Output from wheels to lightboard
    SEARCH c_plugb FOR p_char.
    p_char = c_alpha+sy-fdpos(1).
  ENDIF.

ENDFORM.                    "plugboard
*&---------------------------------------------------------------------*
*&      Form  index_wrap
*&---------------------------------------------------------------------*
* This is used to correct the wheel index in case of wrap-around
* required to make the linear wheel string act like a circular wheel
FORM index_wrap CHANGING p_i TYPE i.
  IF p_i > 25.
    p_i = p_i - 25.
  ELSEIF p_i < 0.
    p_i = p_i + 25.
  ENDIF.
ENDFORM.                    "index_wrap
*&---------------------------------------------------------------------*
*&      Form  set_wheel
*&---------------------------------------------------------------------*
* Set wheel characters so start position charcater is at position 1.
* EG :
* Wheel 1 with start position is, say, W
* EKMFLGDQVZNTOWYHXUSPAIBRCJ
* -------------^------------
* becomes:
* WYHXUSPAIBRCJEKMFLGDQVZNTO

FORM set_wheel USING     p_wheel_in  TYPE char26
                         p_start     TYPE char1
                CHANGING p_wheel_out TYPE char26.


  DATA: l_index TYPE i,
        l_char  TYPE char1.

  CLEAR p_wheel_out.

  SEARCH c_alpha FOR p_start.
  l_index = sy-fdpos.

  DO 26 TIMES.
    IF l_index > 25.
      l_index = 0.
    ENDIF.

    l_char = p_wheel_in+l_index(1).
    CONCATENATE p_wheel_out l_char
    INTO p_wheel_out.

    l_index = l_index + 1.
  ENDDO.


ENDFORM.                    "set_wheel

Create sample web service to save data in Java Table using EJB and JPA.

$
0
0

  These documents will help you to creating the web service for updating the data in java table using EJB and JPA.

1.     Create Dictionary DC from Dictionary Perspective.

1.png

2.     Create Table in dictionary.

2.png

3.     Build and deploy the Dictionary DC.

4.     Create EJB  application-Select DC type as EJB Module.

4.png

5.     Give EJB application name and click next.

5.png

6.     Select JPA and finish.

6.png

7.     Create Enterprise application for EJB application .

7.png

8.     Give name of enterprise application.

8.png

9.     Add  ejb application(test_app) to ear project and finish.

9.png

10.     Select Sap data source aliases provider module of the ear DC from project facets and apply.

10.png

11.     Check alias name of data base in the ear app.

11.png

12.     Open data-source-aliases.xml from META-INF folder and note the alias name.

12.png

13.     Create  connection from EJB application to dictionary.

13.png

14.     Define Alias name in persistence.xml.

14.png

15.     Generate Entities from Table in EJB.

15.png

16.     After creating the entity class, code as below.

16.png

17.     Create class for dto in EJB.

17.png

18.     Generate the getter and setter for this variable.

18.png

19.     Create an interface in the EJB DC and declare save method as below.

19.png

20.     Create a session bean in EJB DC.

20.png

21.     Include Entity Manager and Persistence Context in session bean.

21.png

22.     Define save operation in session bean.

22.png

23.     Create a web service for session bean.

23.png

24.     Build and deploy the EAR and EJB project.

25.     Test the web service from WSNavigator.

JSP, Servlets, Java Server Faces (JSF), Web Service(WSDL), MySql, MongoDB Project (PART 1)

$
0
0

 

This tutorial presents a project created with the mentioned technologies. Through the Web Service you interact with the server also receive a confirmation answer. It also shows the double independence of the database which was obtained through a DB Layer. We have the independence of the SQL, or NON-SQL Database, but also the independence of what SQL Database we want to use, also the independence of the ORM (Object Relational Mapping)

Viewing all 50 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>