Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Wednesday, July 24, 2013

Hitting the Jackpot

In many cases we, as developers, will come across a situation where we need to refactor lots of code in a very specific way. To explain I'll use a recent example I've run into... upgrading an enterprise application for Java EE 7. Java EE 7 applies more constraints onto the PostConstruct method, specifically preventing you from throwing checked exceptions from the method. Glassfish 4 fails deployment with the following message:

Exception while deploying the app [my.fake.company.enterpriseportal_application_war_2.7.0-A8-SNAPSHOT] : The lifecycle method [initialize] must not throw a checked exception. Related annotation information: annotation [@javax.annotation.PostConstruct()] on annotated element [public void my.fake.company.enterpriseportal.ui.admin.livecycle.ecn.MissingEcnJdbcDao.initialize() throws my.fake.company.enterpriseportal.ui.admin.livecycle.ecn.MissingEcnDaoException] of type [METHOD]

Well, the good news here is that it's a very explicit message. I know exactly what I have to do, but how many places have we done just that? Glassfish tells me about one instance of this problem, but there might be many scattered through our 50+ artifacts. Now we could fix the problem by hand, scouring each of our libraries one at a time looking for this problem, or we could hit the  Jackpot . Jackpot is a tool developed by one of the NetBeans developers that allows for large-scale refactoring from the command line.

How it works?

At it's heart Jackpot is a fairly simple tool, once you figure out the ins and outs. The first being, don't try to build it from source code, the build available for download may be slightly out of date but will save you some large headaches; trust me. Go ahead, download it. Once you have it downloaded and unzipped you can execute it on your source code with a command like 

jackpot --hint "System out / err" src/main/java/
For a list of all available hints run "jackpot --list"

In this example we're using one of the built-in features of Jackpot. Since it is somewhat integrated with NetBeans, all the NetBeans refactoring patterns are available to you via the "–hint" argument. This hint checks for any lines that print directly to System.out or System.err; but that's not that helpful.  Firstly, this will only tell you about the problems, it's not going to fix them; and secondly, that's not what we're looking for! Let's talk about automatic refactoring first... because it's easier. To have jackpot automatically fix any issues that it can, you just add the "–apply" argument to you command, so you'll have something like this

jackpot --apply --hint "System out / err" src/main/java/

In this example the offending lines will simply be removed. I hope you didn't do any real computing in a println command!

Custom Rules

The rules formatting has been integrated into Netbeans as of NetBeans 7.1, but I'm not sure where it's used.

Now, to fix our problem. No rule that NetBeans provides will fix our problem, instead we'll need to create our own. The formatting of rules is specific to Jackpot/NetBeans. The documentation available is a little scarce, I've searched through the NetBeans site and the wiki space and have found only these four pieces of documentation:

  1. https://bitbucket.org/jlahoda/jackpot30/wiki/RulesLanguage
  2. https://bitbucket.org/jlahoda/jackpot30/wiki/RulesLanguageAdditionalDocs
  3. https://bitbucket.org/jlahoda/jackpot30-demo-examples/src/0f396ef509cb5ae88933abf50e39442e8aea7923/src/META-INF/upgrade/j.l.Thread.sleep.hint?at=default
  4. http://webcache.googleusercontent.com/search?q=cache:Bej5PnlBPH8J:netbeans.org/kb/docs/java/editor-inspect-transform.html+&cd=2&hl=en&ct=clnk&gl=ca (the NetBeans site was down while I was trying to access it)

Each of these documents only provide a small amount of information regarding the rules, but it was enough to get me going. The rules are divided into two main pieces, the pattern to match and the fix-pattern to apply. If you're only searching and not planning on fixing, you don't need the fix-pattern section, but if you run jackpot with "–apply" it will remove the lines, that's the default action. 

Pattern Matching

The first section, the pattern matching section, is used to tell the system what needs to be found for this rule. In our case we want to look for all methods that are annotated with @PostConstruct. Jackpot is not looking for the specific text "@PostConstruct" and if you set a rule with that text it wouldn't likely find anything. That's because it requires fully qualified class names (unless using custom imports, but let's not go there). This means we're really looking for @javax.annotation.PostConstruct. OK, that's easy enough, but we also need to look for the method, because we need to see if it has an exception too.

To look for the method we'll need two different types of variables. The different variable types are described in this document. The two types we need are:

This rule only catches PostConstruct methods that throw a single exception, you can use $exception$ to catch multiple exceptions, but it can't be used for the fix-pattern.
  1. The "any expression" one, simply noted by using the $ at the beginning of the variable name. This type of variable will be used for the method name and the exception type that is thrown.
  2. The "any number of statements" one, noted by a $ at the beginning an $; at the ned of the variable name. This type of variable will be used for the method body.

Using this information about variables, we'll end up with a pattern like

@javax.annotation.PostConstruct
public void $name() throws $exception { $stmts$; }
;;

Note the ";;" at the end of the rule. This deinfes the end of the rule and emans you can have multiple rules in one file. The rule we created is likely fine and will likely only catch what we're looking for anyway, but, the Exception we're trying to deal with specifically says checked exceptions. If we defined a method that "throws MyRuntimeException" in the definition for documentation purposes, we'd catch that method as well. So far we haven't seen a way to deal with that, so... introducing "Conditions."

Conditions can be added to the end of both sections, I'll explain how conditions work on fix-patterns later, but for now lets focus on the pattern for matching. A condition helps determine if the pattern actually does match by providing more validation capabilities. In our case we'll check the type of the "exception" variable. For more conditions see this document. In Java to check the type of an object against a class we use "instanceof," and in the Jackpot rule language we do the same. Conditions are defined at the end of the rule so our new rule looks like this

@javax.annotation.PostConstruct
public void $name() throws $exception { $stmts$; } :: $exception instanceof java.lang.Exception
;;

Now, we can run this rule right now using 

jackpot --hint-file /path/to/rule src/main/java/

This will list all occurrences that match our custom rule.

Fixing the Problem

To start the fix pattern of the rule you use the "=>" on a new line. When defining the fix you can reuse the variables that you defined in the pattern matching section of the hint. In our case, we'd just like to catch whatever exception is thrown and maybe print it out. Our fix for this pattern should look something like:

public void $name() {
    try{
       $stmts$;
    }catch($exception ex){
       ex.printStackTrace();
    }
}

which means our resulting rule will be:

@javax.annotation.PostConstruct
public void $name() throws $exception { $stmts$; } :: $exception instanceof java.lang.Exception
=>
public void $name() {
   try{
      $stmts$;
   }catch($exception ex){
      ex.printStackTrace();
   }
}
;;

I mentioned earlier that you can apply conditions to fix-patterns as well and I wasn't lying. The truth is that you can have many fixes and Jackpot will use the first applicable fix. This is not applicable in this scenario, but if we hop over to the Jackpot demos we can look at j.l.String.hint. This rule defines two different ways to fix the problem, one if the JDK is greater than or equal to JDK6 and one to use otherwise. Each fix gets started with the "=>" delimiter and have conditions appended to them with the "::" operator.

Conclusion

Jackpot is very powerful, and even more powerful when you consider the scripting capabilities. For example, we could write a script to download all of our repositories and crawl through them fixing new problems we have defined. Whether those new problems are based on upgrade woes as described above, or simply to deal with API changes we make within our code we can automatically refactor all of our code and not miss any required change.

Wednesday, November 14, 2012

Injecting power with the CDI Instance Interface - Part 2

In my last post I described a way to programmatically inject a specific instance via the Instance interface. In this post I'll use the Instance interface again, but this time to inject many instances of an Object.

To start, I'll discuss why you might want to do this. One of the most common reasons I've found is in a modular application where you include different modules into one larger application. When you do this things like installers or the menu system needs to be set-up for each module. In this example we'll look at providing a dynamic menu system.

Menu Classes

Our menu is not going to be fully featured, it actually won't do anything but provide categories and options. We're going to create the following simple classes
MenuCategory.java
    public class MenuCategory {
        private String name;
        ... Accessors and Equals and HashCode Here... 
    }

MenuOption.java
    public class MenuOption {
        private MenuCategory category;
        private String name;
        ... Accessors and Equals and HashCode Here...
    }
We'll also create a Menu class that we can add all of our Options. Adding them to this class will push them into a map that uses the category as the key. You'll also notice the @Alternative qualifier. This is so that when we inject the Menu later the CDI container won't be confused.
Menu.java
    @Alternative
    public class Menu {
        private Map<MenuCategory, List<MenuOption>> menuOptions;
    
        public Menu(){
            menuOptions = new HashMap<MenuCategory, List>(10);
        }
    
        public void addOption(MenuOption option){
            if(!menuOptions.containsKey(option.getCategory())){
                menuOptions.put(option.getCategory(), new ArrayList());
            }
            menuOptions.get(option.getCategory()).add(option);
        }

        public Map<MenuCategory, List<MenuOption>> getMenuOptions() {
            return menuOptions;
        }
    }

Menu Option Provider and Menu Producer

Next we need a common way to provide the Menu Options, and we have an interface to the rescue.
public interface MenuOptionProvider {
    List<MenuOption> getMenuOptions();
}
And now we can start the fun with instances, first we'll start by making our class
public class MenuProducer {
    ...
}
And next we'll inject our Instance interface.
    @Inject @Any Instance optionProviders;
Now that we have our Instance, instead of limiting it with a qualifier, like we did in the last post, we're going to use all Instances it can find. So, instead of using the select and get methods, we're going to take advantage of the fact that it is Iterable.
    @Produces public Menu produceMenu(){
        Menu menu = new Menu();
        for(MenuOptionProvider provider:optionProviders){
            for(MenuOption option:provider.getMenuOptions()){
                menu.addOption(option);
            }
        }
        return menu;
    }
}
And that's it, we now have our dynamic menu, if you want to see it at work implement the MenuProvider like this:
public class FileMenu implements MenuOptionProvider {

    @Override
    public List getMenuOptions() {
        MenuCategory category = new MenuCategory();
        category.setName("File");

        List options = new ArrayList();

        String[] optionNames = {"Open", "Save", "Close"};

        for (String optionName : optionNames) {
            MenuOption option = new MenuOption();
            option.setCategory(category);
            option.setName(optionName);
            options.add(option);
        }

        return options;

    }
}
Download the source of this example here.

And that concludes our example today. I hope you've enjoyed this post and that it has helped you in some way.

Wednesday, November 7, 2012

Injecting power with the CDI Instance Interface - Part 1

The Instance interface in CDI is a powerful tool for creating flexible libraries and applications. In this post I'll examine a couple different ways to use Instance in your application and gain the power of programmatic injection. First, lets talk about Instance a bit. For detailed informaiton, see the Weld Reference. Instance allows a programmer to decide, at run-time, via code, which Object should be injected. This is very powerful and can be used in a few different ways. You can use the Instance interface to select a specific instance, or you can use it to run through all instances. We'll look at both of these cases with some simple examples. The first example will be creating a Factory object and will only use one instance at a time. The second example, where we'll run through many instances will wait until another post.

The factory example

In this example we'll dynamically inject a single instance that will construct an Object for us. Using this method we can create a factory that is so easy to extend that you don't need to modify it to add functionality. In this example we'll have a couple different Objects we want to create in our factory, and for fun, they won't be related whatsoever.
FirstObject.java

    public class FirstObject{
        public String value;
    }

SecondObject.java

    public class SecondObject{
        public Integer intVal;
    }
OK, we have two really simple objects that share no inheritance, and we'll have our factory create both of them; but our factory is actually going to ship the work off-shore, it will out source the work to specialized shops that we'll call ObjectBuilder.
public interface ObjectBuilder {
    Object build(String value);
}
We're providing it with some extra information just so that we can see it do more than just create a new instance. These builders will be simple to write and here they are:
FirstObjectBuilder.java

    public class FirstObjectBuilder implements ObjectBuilder{
        public Object build(String value) {
            FirstObject object = new FirstObject();
            object.value = value;
            return object;
        }
    }

SecondObjectBuilder.java

    public class SecondObjectBuilder implements ObjectBuilder{
        public Object build(String value) {
            SecondObject object = new SecondObject();
            object.intVal = Integer.parseInt(value);
            return object;
        }
    }
Finally, before we get to making our factory we need a Qualifier. This qualifier will allow us to inject the specific ObjectBuilder that we want.
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER})
public @interface BuilderFor {
    Class value();
}
We also need an Annotation Literal that we can manipulate during the CDI look-up.
public class BuilderForLiteral 
    extends AnnotationLiteral 
    implements BuilderFor{

    private Class clazz;

    public BuilderForLiteral(Class clazz) {
        this.clazz = clazz;
    }

    public Class value() {
        return clazz;
    }
}
The annotation literal provides a "physical" object that we can manipulate programmatically to represent what we're looking for.

Now that everything is in place, lets play with Instance and make our factory.
public class MyFactory{
    ...
}
The first thing we need in our factory is an Instance, so we'll inject that.
@Inject @Any Instance objectBuilderInstances;
Next, lets define our method for building:
public Object build(Class typeToBuild, String value){
    ...
}
Now, we're going to add a qualification to our Instance. This will limit the look-up to the specific ObjectBuilder we're looking for.
    BuilderForLiteral builderForQualifier = new BuilderForLiteral(typeToBuild);
    Instance qualifiedInstance 
        = objectBuilderInstances.select(builderForQualifier);
So, we now have a qualified Instance... great... we still don't have the object. But don't worry, that's the next step.
    ObjectBuilder builder = qualifiedInstance.get();
We've now injected our ObjectBuilder programmatically, the rest is pretty straight-forward.
    return builder.build(value);
And the Factory class altogether looks like this:
public class MyFactory {
    @Inject @Any Instance objectBuilderInstances;
    
    public Object build(Class typeToBuild, String value){
        BuilderForLiteral builderForQualifier = new BuilderForLiteral(typeToBuild);
        Instance qualifiedInstance 
                = objectBuilderInstances.select(builderForQualifier);
        ObjectBuilder builder = qualifiedInstance.get();
        return builder.build(value);
    }
}
This is a very powerful pattern that you can use throughout your applications, and this is just one example of using the Instance interface. Soon I'll post again about using the Instance interface to access multiple instances.

I once again want to say that this code is not production ready. For example, before we get the ObjectBuilder you should check to see if the Instance is unsatisfied or ambiguous and throw an Exception. You can use qualifiedInstance.isUnsatisfied() and qualifiedInstance.isAmbiguous() to do this.

I hope you've enjoyed this post and come back again later for more.

Wednesday, October 24, 2012

Injecting Configuration Values with CDI in a Java EE environment

Commonly while developing a web application there is need to configure an application differently per deployment. This configuration is generally handled by an external data source such as a properties or XML file. In this post I will examine a novel way of retrieving these configuration values using CDI injection.

My first thought about injecting Configuration values led me to inject a Configuration object and using this object I could access the configuration values. This is kind of clunky as I never really wanted the configuration object just the values. My code would end up looking like this:
@Inject Configuration conf;

private void useConfig(){
    System.out.println(conf.getValue("myConfig"));
}
But why can't I just inject the value directly. What I would like to do is this
@Inject @Config("myConfig") String myConfig;
Well, I'm not quite able to do that either but I can get pretty close to this. Ultimately, I was able to come up with a configuration library that allows me to inject configuration like this
@Inject @Config @ConfigName("myConfig") String myConfig;
So how did I do it? There's a few pieces to this puzzle. There is a CDI producer, a CDI qualifier, a plain old annotation and a data access object to retrieve the configuration values. Let's start with the qualifer.

Configuration Qualifier

A qualifier in CDI is a way to limit what will be injected. We will use this qualifier on String objects to allow our producer, which we'll come to later, to provide the values. A CDI Qualifier is actually just a regular annotation that is annotated with @Qualifier. Below is the qualifier we will use.
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER})
public @interface Config {
}

Configuration Name Annotation

The configuration name allows us to inject the value by the name that we refer to them in the configuration data source. This annotation is quite simple and will contain a value, which will be the configuration name. If you already know about qualifiers, you may be asking why we have this annotation and why not include the name in the qualifier. The problem is that if you included the name in the qualifier you'd have to have a separate producer for every configuration value. This is because when CDI does it's look up for objects and producers that match the injection, the value of the qualifier is actually used.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER})
public @interface ConfigName {
   public String value();
}

Configuration Data Access Object

We will need some way of accessing our configuration values, whether they're stored in a properties file, and XML file, a database, or somewhere else, we just need a common way to access them. To this end, we'll just describe an interface and you can provide an implementation.
public interface ConfigurationDao{
    String readValue(String name);
}
Now that all of that is out of the way, let's see the producer.

Configuration Producer

So, to start, we need a class that will produce the configuration values, lets call it ConfigurationProducer.
public class ConfigurationProducer {
Next, we'll need access to the configuration data, so let's inject that.
   @Inject ConfigurationDao dao;
And now the actual producer method. A producer method, as defined by the weld reference,
... is a method that acts as a source of bean instances.
More information on Producer Methods can be found in the Weld Reference. This needs to be annotated as a Producer and qualified with Config, the qualifier we made earlier.
   @Produces @Config public String getConfigurationValue(...){
Next, we need more details about where we're injecting, maybe information about the point of injection. Well, it just so happens that part of the CDI specification is that Producers can have access to the InjectionPoint.
   @Produces @Config public String getConfigurationValue(InjectionPoint p){
You can see the Weld Reference for more information on the Injection Point. With the injection point, we can actually access the ConfigName annotation.
       String valueName = null;
       for(Annotation annot:p.getAnnotated().getAnnotations()){
           if(annot instanceof ConfigName){
               log.debug("Found a config name annotation");
               ConfigName configNameAnnot = (ConfigName)annot;
               valueName = configNameAnnot.value();
           }
       }
 
And now that we've determined the Configuration Name all we have to do is look it up and return the value.
       return dao.readValue(valueName);
And that's it. Now, in any class (that supports injection) you can simply code
@Inject @Config @ConfigName("super.awesome.config") String configValue;
and the producer will handle the rest. On top of this, you have further options with the producer. You can add another annotation for default values. If this annotation is found and there is nothing in the configuration data source this value would be used. You can also have it provide types other than String, simply add another method to your producer that provides, lets say, an Integer instead of a String. There are many further options that you could tackle, you could even include multiple data sources with some simple tweaks.

Finally, i just want to point out that the code on this page is not production ready. The DAO should likely be able to throw an Exception if there is an error accessing the data source, and it might be wise for the Producer to throw an exception if the ConfigName annotation is not found, but, for simplicity's sake these things are not here.

Wednesday, December 1, 2010

Sapping up your Java Code - Part 2: Functionality

If you're coming in late to this series, you might want to first read Part 1, since you can't really do anything without it.

The JCoFunction

A JCoFunction is an object in Java that represents a Remote Function Call. That is, a function in SAP that is "remote enabled." If you don't know of any of these, ask your SAP Team, probably an ABAP developer, to provide one for you. Nothing on the Java side will work without a RFC in SAP. Here's how it works:

  1. The Java program connects to the SAP system (see Part 1)
  2. The Java Program requests the function from the SAP system.
  3. The SAP system returns the meta-data of the function which is then turned into a JCoFunction object.
  4. The Java program populates the fields of the JCoFunction
  5. The Java program sends the function to SAP to be executed
  6. SAP sends the data back from the SAP call and it gets shoved right back into the same object.
  7. The Java program reads the information out of the JCoFunction and does whatever is needed.

This is essentially how SAP JCo works to communicate between systems. There are other things that can be done, like having SAP call out to a remote Java system, but that is outside the scope of this post. The code to do all of this is quite simple, requiring only a few objects, and the JCoDestination that we learned about in the previous post. I told you that previous post would be important.

In our demo, we'll try to connect to an SAP system and retrieve information about a customer. The Function in SAP will be named "Z_GET_CUSTOMER." If you're new to SAP, you might ask, why the 'Z?' The 'Z' actually means that the function that is being called was created by the customer, the customer being your company. In some rare cases, they also use 'Y' but that is not very common. The structure of the data will be similar to this:
Import Parameters (to be sent to SAP):
   CUSTOMER_ID     INT       An ID that identifies the Customer in SAP
Export Parameters (to be retrieved from SAP):
   STATUS          STRING    'S' is successful
   NAME            STRING
   LOCATION        STRING

As you can see from our example structure, we're not expecting this call to do much, but at least it's something.

Retrieving the Function from SAP

In step 2 listed above, the Java application request the function from SAP. How do we accomplish this? Well, the first thing we need is the JCoDestination object. The JCoDestination is your connection to SAP. From it, you have access to the JCoRepository through getRepository(). This is our first step. Our next step is to retrieve the function, and this couldn't be simpler. All we need to do is request the JCoFunction from the Repository through getFunction(String functionName).

Boiling that last paragraph down into a succinct hierarchy, you get this:
JCoDestination provides
   - JCoRepository provides
      - JCoFunction

So now the code. Generally, when I do this, I perform all actions in one line. This makes the line slightly more complex, but the repository is only used (in most cases) for providing functions, and can be disregarded right afterwards, so it makes little sense to store it in a variable, even temporarily.

JCoDestination _destination = ...;
JCoFunction f = _destination.getRepository().getFunction("Z_GET_CUSTOMER");

This provides the JCoFunction to you, but it also does quite a bit more behind the scenes. The repository actually caches the meta-data in the background. This means that the next time you request the same JCoFunction, it takes less time because the repository already has the meta-data required for creating the JCoFunction.

Populating the JCoFunction

Providing data to SAP, is quite a simple procedure. All you need to do is set values in the ImportParameterList. The ImportParameterList is actually a JCoParameterList, which is also used for export, and has one method for setting all the values you require. To use this method, you provide the name of the field within the Import Parameters, in our case "CUSTOMER_ID." So we provide it our Customer ID, we'll just say 1.

JCoParameterList imports = f.getImportParameterList();
imports.setValue("CUSTOMER_ID", 1);

Here we see, setting a value with an int. But an int is only one type of data we might want to provide. Sure, we could say that auto-boxing in Java 5 makes this possible by wrapping it as an Integer object and supposing that the setValue just accepts objects, but that's not what has happened here. The truth is, that the SAP Programmers have overloaded the setValue method to accept pretty much anything you can throw at it. This means that, even in Java 1.4, you can provide all your import parameters by using this one function.

Executing the call on the SAP System

Assuming that you have all your security settings are correct, making the call should be as simple as calling the execute method on the function. To call this method you need to provide the JCoDestination again, but this is a minor matter.

f.execute(_destination);

Done. Nothing else to do to execute the function. There is no return value, which in my opinion is unfortunate. I would have preferred the separation of input and output into different objects, like the way SQL Statements provide a ResultSet, but that is not how SAP designed the JCo Connector.

Reading the Information

All the information that SAP returned will be held within your original JCoFunction. You'll access them from ExportParameterList, and in some cases, TableParameterList. ExportParameterList, is where all your data should reside, as is what SAP recommends; but depending on the version of SAP, and the age of your SAP Programmers, that may not be true. TableParameterList was where lists of data would be returned, like if we wanted to return multiple customers, but at some point, SAP allowed import and export parameters to be tables as well.

So, reading from the ExportParameterList is as simple as this:
String status = f.getExportParameterList.getString("STATUS");
if("S".equals(status)){
    System.out.println("Customer Name is " + f.getExportParameterList.getString("NAME"));
}else{
    System.err.println("No customer found");
}

And that is all, in this post, I've shown how to use our previously established JCoDestination to retrieve and execute a function. As a side note, the JCo Connector version 3 was leaps and bounds above JCo 2. JCo 2 suffered from an API that didn't makes sense and complexity that was not required.

Wednesday, November 24, 2010

Sapping up your Java Code - Part 1: The connection

SAP is an Enterprise Resource Planning system which controls a large market share. In many big companies SAP is the backbone that provides and relates information from most, if not all, departments. Having so much data, being able to access that information from outside the system becomes imperative. At the company I work for, we use Adobe LiveCycle to create paperless workflows that send and retrieve information from the SAP system. This enables our users to have a clear, concise... pretty... interface into SAP for common tasks. We are currently supporting 1000 users with this method. (Also, it only uses up one license on the SAP side). So, how does it work...


Let's talk about setting up a connection to SAP. Well, the first thing that you need is the SAP JCo. This is not freely available to everyone, you need an account at the SAP Service Marketplace. This site very poorly laid out, and it might be hard to find... I'd include a link right to the page, but I'm not sure that it would be reliable. I recommend doing a search for "JCo Download" and then when that search fails to return anything, click on the "Documents" section. You will have multiple options available for download, Windows/Linux/etc... pick whichever one applies to you. Make sure you add the jar and dll/so to your classpath properly. This post only talks about JCo3, I had worked with JCo2 previously but it wasn't very reliable under large amounts of processing, so I'd recommend going straight to JCo3.

Wahoo... we have the SAP JCo, now, how do we connect? The easiest way is not very efficient at all. In fact, it's a pretty dumb way to do it. The first thing you'll do is create a Properties object in your java code. You'll then populate it with some data, and then you'll write it to a file with the extension ".jcoDestination." You then tell JCoDestinationManager to get the destination by providing it the file name without the extension, here, let me show you some code:

//Other Class definition up here
...

//Don't just throw the exception, do actual error handling, this is just for
//demo sake

private JCoDestination makeConnection() throws Exception {
//Make the properties object
Properties p = new Properties();
p.setProperty(DestinationDataProvider.JCO_ASHOST, host);
p.setProperty(DestinationDataProvider.JCO_SYSNR, systemNumber);
p.setProperty(DestinationDataProvider.JCO_CLIENT, client);
p.setProperty(DestinationDataProvider.JCO_USER, userName);
p.setProperty(DestinationDataProvider.JCO_PASSWD, password);
p.setProperty(DestinationDataProvider.JCO_LANG, language);
p.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, poolSize);
p.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, poolPeakSize);

//Write it out to a file... because file I/O is so nice
FileOutputStream fos = new FileOutputStream("sapconn.jcoConnection");
toProp().store(fos, "SAP System Connection");
fos.close();

//And read it back in...
JCoDestination destination = JCoDestinationManager
.getDestination("sapconn");
return destination;
}


As you can see it's a lot of pointless work to get the connection object. you could circumvent much of this by saving the first jcoDestination file that you create and re-using for every time you need to make your connection. Nonetheless, I think SAP made a very poor design choice when they limited the creation of "Destinations" to file I/O. There is an alternative to this method which is probably much more efficient, but also much more work. It involves implementing the DestinationDataProvider, registering it with the SAP JCo, and then creating the Destination.

The JCoDestination object is not quite a connection to SAP, but it's the closest thing you'll get. The JCoDestination is essentially a pointer to the connection pool. When you execute anything that needs to contact SAP it uses a JCoDestination to see exactly where it should be going. Now, let's talk about those properties we were just setting.

Table 1: SAP Configuration Properties


Property NameDescription
JCO_ASHOSTThis is the host, or server, that is running your SAP instance.
JCO_SYSNRThe is the System Number for your SAP system. If you're strictly a Java programmer, you're probably best to just ask what this is from someone in your SAP team. As far as I can tell, this is generally used to segregate Development and Production systems.
JCO_CLIENTAgain, this is something you'll have to ask for. The client seems to be a way to segregate some functionality of the system. Such as, functionality for different plants.
JCO_USERThis is the user that your Java code will use to connect to the SAP system.
JCO_PASSWDAnd this is the password related to that user.
JCO_LANGThe Language you want to use for the connection. I use EN, for English.
JCO_POOL_CAPACITYThis setting is for performance. It determines how many connections to SAP it will open at a time. You'll have to play with this setting, I'd start at 50, or 100 for moderate user load.
JCO_PEAK_LIMITOn top of the capacity limit, there is a peak limit. The capacity is for normal operation, whereas the peak, is for those times when your server is being pounded by user requests. The peak limit will allow for extra connections to be created as needed, over the initial capacity. These connections will be destroyed as soon as they are not in use, where as the connections specified in the capacity setting, will remain. This setting should be something larger than the CAPACITY, but it is up to you to determine what value is best for your application.

And there you go, you're connected to SAP. From here you're going to need access to an RFC (Remote Function Call) if you really want to make the system do something. Coming soon will be a discussion on the JCoFunction object and how to use it.

Wednesday, August 18, 2010

Creating a Maven Project in Eclipse



In this very quick post, I will show you how to Install the m2Eclipse plugin, and use it to create a Maven Project. I'm actually just writing this quickly to support another post. So, let's get started.

Install the m2Eclipse plugin.



Open Eclipse and go to "Help > Install new Software"



Add a new software site

Enter a name, I suggest m2Eclipse
Enter the Location: http://m2eclipse.sonatype.org/sites/m2e



Click OK

Select the Site (if not already selected)
Select the Plugin and Click Next



Click Next and accept the terms until the plugin is installed.

Create a Maven Project



Select "File > New > Project..."
Select "Maven Project"

Click next.
On the next screen, accept the defaults and click next.
Select the maven-acrhetype-quickstart and click next.
Enter the Group ID, Artifact ID, version and default package of your new Maven Project and click Finish.


That's it! You're done. Sorry if this seems a little rushed, I really want to talk about Weld instead.

Simple Java-SE Application with Weld and Maven

Creating a Java-SE (Desktop) Application that uses Dependency Injection from Weld can be a very simple process. In this quick example, I use Maven and Weld-SE to create a very simple Dependency Injected application.

The technologies that we use in this tutorial are Dependency Injection, provided by Weld, a JSR-299 Implementation, and Maven as our project builder.

The first step to creating a Welded Desktop Application, is to create a Maven project from the maven-archetype-quickstart archetype. There are many ways to do this, one option is from the command line with "mvn archetype:generate". I prefer to use m2eclipse, a plugin for eclipse (see Creating a Maven Project in Eclipse)

Ok, we have our Maven project. Now, let's add our dependencies to the pom.xml. Luckily, there's only one that is needed. The Weld-SE dependency:
    <dependency>
     <groupId>org.jboss.weld.se</groupId>
     <artifactId>weld-se-core</artifactId>
     <version>1.1.10.Final</version>
     <type>jar</type>
     <scope>compile</scope>
    </dependency>


Yay, we have everything we need to start writing our code now. Well, not quite. We need an "empty" beans.xml file. So we create one at src/main/resources/META-INF/beans.xml. This file contains very little, but is not technically empty. It contains the following:
<beans xmlns="http://java.sun.com/xml/ns/javaee" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
      http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

This file tells Weld that this application uses CDI (Context Dependency Injection). This is very important, otherwise, why would we be using Weld in the first place.

To make this post actually worthwhile, we'll make a class to be injected into our main code. It's going to be really simple, and not follow best practices at all.

package com.blogspot.aprogrammersguide.weldse;

public class InjectedClass {
 public String value = "Hello World!";
}


Let's play with some Weld now. We'll make our really simple main class. Our main class will use the annotation @Inject to shove an InjectedClass object into our main class.

public class Main {
 
 @Inject
 private InjectedClass injected;
}


That's pretty sweet, but this application still does nothing... there's not even a static void main... And, it doesn't need one, it does however need a different method.

...
    public void main(@Observes ContainerInitialized event)
    {
     System.out.println(injected.value);
    }
...


This is what Weld-SE expects. Basically, this tells Weld that main (or whatever else you wanted to name it) is watching for the "ContainerInitialized" event. The ContainerInitialized event is when Weld is done being initialized; this is when the application should start.

So, here's the full source of main. I like to give the full source, so you don't have to guess as to what you need to import.
package com.blogspot.aprogrammersguide.weldse;

import javax.enterprise.event.Observes;
import javax.inject.Inject;
import org.jboss.weld.environment.se.events.ContainerInitialized;

public class Main {
 
    @Inject private InjectedClass injected;
 
    public void main(@Observes ContainerInitialized event){
     System.out.println(injected.value);
    }
}

So, let's run this and see what we get. You might be asking, how do we run this? You told us that we don't need a static void main, but Java requires one. We'll use the one that the nice Weld developers provided us, org.jboss.weld.environment.se.StartMain.

So, to run this we'll go to the command prompt. Go to the root of your Maven project and run
mvn exec:java -Dexec.mainClass="org.jboss.weld.environment.se.StartMain"


And there we go. We have a Java-SE Application that uses Weld for Dependency Injection. Obviously though, you'll want to make this a Jar before deploying it, so just remember to use org.jboss.weld.environment.se.StartMain as the mainClass in your Jar, instead of the main class you developed. But wait, what about command-line parameters?

Weld-SE does have the capability to handle this. All you'll need to do is modify your main method. Change it to:
public void main(@Observes ContainerInitialized event, @Parameters List parameters)

and import org.jboss.weld.environment.se.bindings.Parameters. The parameters object will contain all the command-line parameters.

One last interesting side-note that comes from all this. You now have the ability to have multiple main methods in multiple classes by having other methods use the @Observes annotation with the ContainerInitiatized event. Weld does handle these, but it is quite a dangerous thing to do. Weld will execute one of these at a time. One will finish and then the next will start. If you want to prove it, add this class:
package com.blogspot.aprogrammersguide.weldse;

import java.util.List;
import javax.enterprise.event.Observes;
import org.jboss.weld.environment.se.bindings.Parameters;
import org.jboss.weld.environment.se.events.ContainerInitialized;

public class OtherMain {
    public void main(@Observes ContainerInitialized event, @Parameters List parameters)
    {
  for (int i = 0; i < 10; i++) {
   System.out.println("Other Main");
   try {Thread.sleep(1000);} catch (InterruptedException e) {}
  }
    }
}

One of these will execute first, and then the other, and I'm not sure if there is a way to predict which one will run first. If you add a similar for loop into your first main, you can see that one runs first, and then the other, not simultaneously.

Anyways, that's my post on Java-SE and Weld. hopefully it helps you out. For more information on Weld, visit the Weld Site.

Update: Changed the Weld SE dependency to be something a bit more recent.

Tuesday, June 29, 2010

Singletons are for losers and bad frameworks...

I recently read Miško Hevery's postSingletons Are Pathological Liars and had trouble with rationalizing this. For a few days I tried to develop a Singleton pattern that would side step the issue. I tried to make the Singleton have default access and then use a proxy class to access it. You'd have to instantiate the proxy class rather than access the Singleton directly. I called this approach "Proxied Singleton." This was great, except for when the Singleton had dependencies, then it all fell apart. I couldn't wrap my head around getting rid of Singletons.

I couldn't comprehend why you would want to completely get rid of them, they're very useful, then I read a few more of his posts. It seems that he's not wanting to get rid of the idea of a Singleton, just the common pattern used for creating them. Essentially, the getInstance() method is the problem. With the getInstance() method you can make a call to the Singleton from anywhere and this makes the code difficult to test and sometimes hard to comprehend. So, let's do away with this pattern.

Now, how would I make sure that my "singleton" only gets instantiated once... well, I'll let Miško answer that ("Where have all the Singletons Gone?"). Great, we're done here, aren't we...? No...

A lot of my work is in a framework that does not allow me to use the factory idea to create single instances of a class. This framework, which will remain *cough* Adobe Livecycle *cough* nameless..., has no ability for me to use a factory method when the application starts and pass those instances around. The framework does allow me to run code when the application starts, but I have no ability to store or pass anything created there to any other objects. So, now what do I do? I have two options, I stick with the crappy Singleton approach, I try to rig up my "Proxied Singleton" class, or I spam the CEO of Adobe until they make their product better. I opted for the last option and now have a restraining order to go along with my problems. I would go my "Proxied Singleton" route, but it essentially gives no advantage and would confuse other programmers (since it's not a standard design). So back to the crappy Singleton approach, with a slight change.

The biggest drawback of the Singleton approach is in it's limitation of being able to change. So, I'll use dependency injection and never call the getInstance() from within the logic classes. This is not completely safe because there is nothing that would stop getInstance() from being used, but I guess I'll have to take my chances. Good thing there is code review. I'll probably look into Google GUICE or Spring to add in some nice dependency management that is not available in LiveCycle, I mean the nameless framework.

You can look forward to some really specific posts coming up, relating to LiveCycle Custom Components and the SAP Jco.

Wednesday, June 23, 2010

Coconuts and Collections

I have a lovely bunch of coconuts, here they are a standing in a row...


But how did we get them standing in a row, how did we make them a bunch? In Java there are multiple ways that you can store your coconuts. You can put them into bag without caring about the order (this would be a HashSet); you can line them up in a row (ArrayList/Vector); you can sort them from smallest to biggest (TreeSet); you can name them (HashMap); and you can name them, and then sort them by their name (TreeMap).

So, lets start from the beginning... There are actually more ways to store your coconuts, but I find these to be the most useful. All of these classes are derived from either the Collection or Map interfaces. A Collection is basically just a group that stores your coconuts, where as a map stores your objects with an easy way to get at them, for example, by name.

The Coconut Class


We're going to start off with a simple coconut class and add more to it later. The song does say that we have big ones and small ones, so we should probably have a way to tell the size of the Coconut.


public class Coconut {
private Integer size;

public Integer getSize() {
return size;
}

public void setSize(Integer size) {
this.size = size;
}

public Coconut(Integer size){
setSize(size);
}
}



HashSet


A HashSet is kinda of like throwing your coconuts in a bag, you're never really sure which one you're going to grab out. The HashSet is designed for speed (if set-up properly), but does not make it easy to get back any specific element.

Example:

HashSet<Coconut> myCoconuts = new HashSet<Coconut>();


Woah! "What's up with the angled brackets?" Well, all the Collections and Map classes are parameterized, also known as generic, classes (as of Java 5). Using parameterized classes means that some method or property of that class is going to use the class that you specified in between the <>. What this means for Collection and Map classes is that the Collection or Map that you create will only accept the specified type of value.

Note: This is a half-truth, parameterized classes work with inheritance, and at run-time, it is possible, due to erasure, that other items could get shoved in there, but you shouldn't need to worry about this second point right now.


And now you ask, "What would happen if I didn't make them parameterized?" Well, the classes will work fine if they are not parameterized, however, they will assume that anything going into them is an Object, which will mean that you'll probably have to cast it back to the correct class before trying to use it. This is actually how these classes worked before Java 5.

OK, back to HashSet. The first thing you'll probably want to do is add an item to the HashSet.

myCoconuts.add(new Coconut(1));


So, it's in there, how do I get it out? Well, HashSets aren't really made to get at one specific item, they're more meant to be iterated over. Iterating over a collection is very easy, and there is a special for loop syntax just for that purpose.


for (Coconut coconut : myCoconuts){
System.out.println(String.format("Coconut that is %d cm around.",
coconut.getSize()));
}


In the code above I use the special for loop syntax to iterate through all the coconuts. For each iteration of the loop the Coconut object that is in myCoconuts is stored in a variable named coconut, which you can access within the loop. So, let's try all of this.



import java.util.HashSet;

public class HashSetTut {
public static void main(String... args) {
HashSet myCoconuts = new HashSet();
for (int i = 1; i <= 10; i++)
myCoconuts.add(new Coconut(i));

for (Coconut coconut : myCoconuts)
System.out.println(String.format("Coconut that is %d cm around.",
coconut.getSize()));

}
}


Now, when we run this, you'll get an output similar to:


Coconut that is 4 cm around.
Coconut that is 8 cm around.
Coconut that is 7 cm around.
Coconut that is 6 cm around.
Coconut that is 1 cm around.
Coconut that is 2 cm around.
Coconut that is 9 cm around.
Coconut that is 3 cm around.
Coconut that is 5 cm around.
Coconut that is 10 cm around.


What happened? That's not the order I put them in. Well, that's what I was saying earlier, when I said "it's like putting them in a bag." They're not organized in the hash set the way you'd expect, and I'm not really going to explain this. If you want to read more about HashSet, see the HashSet JavaDoc, but all you need to know at this point is that it's not going to return the elements to you in any sort of order. In fact, if you run the same example again, it will probably return the items in a different order.

Let's move on...


ArrayList


An array list is not like a HashSet, the array list stores the information in the order you entered it. It also allows you to retrieve a specific object by using an index. So let's modify the above code to use an ArrayList instead. With some really simple modifications we get:



import java.util.ArrayList;

public class ArrayListTut {
public static void main(String... args) {
ArrayList myCoconuts = new ArrayList();
for (int i = 1; i <= 10; i++)
myCoconuts.add(new Coconut(i));

for (Coconut coconut : myCoconuts)
System.out.println(String.format("Coconut that is %d cm around.",
coconut.getSize()));

}
}


And now when we run it, everything is returned in the order we entered them in.


Coconut that is 1 cm around.
Coconut that is 2 cm around.
Coconut that is 3 cm around.
Coconut that is 4 cm around.
Coconut that is 5 cm around.
Coconut that is 6 cm around.
Coconut that is 7 cm around.
Coconut that is 8 cm around.
Coconut that is 9 cm around.
Coconut that is 10 cm around.


A couple things to note here:

  1. It was really easy to change between HashSet and ArrayList because they both implement the Collections interface

  2. All the items returned in the order they were entered



Now, with ArrayList, we also have the ability to get at a specific element using an index. ArrayLists are zero-based arrays and therefore when we specify
myCoconuts.get(2);

We will get the third element that we inserted, in this case, the coconut with the size of 3.


Vector


The vector class has been around since Java 1.0. At this time the collections and list interfaces did not exist, but it was retrofitted in Java 2. ArrayList and Vector are essentially the same, but Vector is synchronized whereas ArrayList is not. What does that mean?... Well, it basically means that the Vector class is safe for use in multi-threading, and ArrayList is less safe. This is not to say that you couldn't use ArrayList in multi-threaded applications, you'd just have to be more careful with it.


TreeSet


The TreeSet class adds a new object into the mix, and there's two way to handle it. The first way is to make Coconut implement Comparable. So, let's take a look at that. We'll need to modify our Coconut class. We'll do two things to the class:

  1. Add the implements Comparable statement to the class definition.

  2. Add the compareTo(Coconut o) method to the class.




public class Coconut implements Comparable{
private Integer size;

public Integer getSize() {
return size;
}

public void setSize(Integer size) {
this.size = size;
}

public Coconut(Integer size){
setSize(size);
}

public int compareTo(Coconut o) {
return getSize().compareTo(o.getSize());
}
}


The compareTo method returns an integer. If the returned integer is 0, then the two items are equal. If two items are equal, the TreeSet will not add the second item. If the integer is greater than 0, then this item is greater than the item that was passed in. If the integer is less than 0, then this item is less than the item that was passed in. Lets modify our ArrayListTut code a bit more to support TreeSets.


import java.util.TreeSet;

public class TreeSetTut {

public static void main(String... args) {
TreeSet myCoconuts = new TreeSet();

for (int i = 1; i <= 10; i+=2)
myCoconuts.add(new Coconut(i));
for (int i = 2; i <= 10; i+=2)
myCoconuts.add(new Coconut(i));

for (Coconut coconut : myCoconuts)
System.out.println(String.format("Coconut that is %d cm around.",
coconut.getSize()));

}
}


I've modified how the elements are added. All the odd numbers between 1 and 10 are added first, and then the even numbers. This is so we can see the TreeSet at work. If I were using ArrayLists in this example I would receive the following output:


Coconut that is 1 cm around.
Coconut that is 3 cm around.
Coconut that is 5 cm around.
Coconut that is 7 cm around.
Coconut that is 9 cm around.
Coconut that is 2 cm around.
Coconut that is 4 cm around.
Coconut that is 6 cm around.
Coconut that is 8 cm around.
Coconut that is 10 cm around.


But with TreeSets I receive:

Coconut that is 1 cm around.
Coconut that is 2 cm around.
Coconut that is 3 cm around.
Coconut that is 4 cm around.
Coconut that is 5 cm around.
Coconut that is 6 cm around.
Coconut that is 7 cm around.
Coconut that is 8 cm around.
Coconut that is 9 cm around.
Coconut that is 10 cm around.


So what happened here... Basically, when adding the item to the set, the TreeSet uses the compareTo method of the Coconut class to determine the position in the set.
Note:If an item is modified after being added to the set, in a way that would affect it's position, it's position in the tree will not change.


What about the other way? Well, the other way is to use a Comparator that is passed in to the TreeSet constructor. Lets see that:


import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetTut {

public static void main(String... args) {
TreeSet myCoconuts = new TreeSet();
for (int i = 1; i <= 10; i += 2)
myCoconuts.add(new Coconut(i));
for (int i = 2; i <= 10; i += 2)
myCoconuts.add(new Coconut(i));

for (Coconut coconut : myCoconuts)
System.out.println(String.format("Coconut that is %d cm around.",
coconut.getSize()));

}

private static class CoconutComparator implements Comparator {
public int compare(Coconut o1, Coconut o2) {
return o2.getSize().compareTo(o1.getSize());
}
}
}


This results in:


Coconut that is 10 cm around.
Coconut that is 9 cm around.
Coconut that is 8 cm around.
Coconut that is 7 cm around.
Coconut that is 6 cm around.
Coconut that is 5 cm around.
Coconut that is 4 cm around.
Coconut that is 3 cm around.
Coconut that is 2 cm around.
Coconut that is 1 cm around.


A couple new things to note here:

  1. It sorted in reverse order. This is because in the CoconutComparator I'm comparing them in reverse. If I compared o1.getSize() to o2.getSize() they would appear in the normal order of things.he comparator can do any arbitrary thing you want it to do, I have it comparing the sizes, but you can make compare the hashCodes if you want.

  2. The comparator took precedence over the Comparable interface on the Coconut class. This is useful if a class that you did not write, or do not want to change already implements Comparable but you need to sort it in a different way.



Note: If sorting speed is of utmost importance to your application, you might be wise to use your own sorting algorithm rather than using the TreeSet. I'm sure the TreeSet implementation is better than a bubble sort, but there are probably many better sorting algorithms that could be used.




HashMap


Maps are different than Collections because they require to entries. The first being the key, and the second being the value. The following shows how you'd create a HashMap:


HashMap myCoconuts = new HashMap();
myCoconuts.put("Ford",new Coconut(5));
myCoconuts.put("Arthur",new Coconut(2));
myCoconuts.put("Zaphod",new Coconut(3));
myCoconuts.put("Marvin",new Coconut(20));
myCoconuts.put("Trillian",new Coconut(8));


Notice that we're specifying two types in the angle brackets here. The first type specifies the type of the key, and the second specifies the type of the value. You do not have to use strings as your key value, although they do prove very useful. The key,value pairing provides some really useful features, mainly, being able to get at a value using the key. For example:


myCoconuts.get("Arthur");


This will retrieve the coconut that we associated with "Arthur." From this, you can easily use it to retrieve any of values contained just by supplying the key.

Iterating through a Map is a bit different than iterating though a Collection. If you're only interested in the values stored with the Map, you can use:


for(Coconut c:myCoconuts.values())
//doStuff


If you are interested in both the key and value, then you need to use the entrySet() method. The entrySet() method returns a set of Entry objects. These Entry objects hold both the key and value.


for(Entry cocoEntry:myCoconuts.entrySet()){
System.out.println(String.format("%s - %d", cocoEntry.getKey(),
cocoEntry.getValue().getSize()));


We are now iterating through the set of Entry objects, rather than a set of Coconuts. To access the Coconut value, we're using cocoEntry.getValue(). To access the key, we use cocoEntry.getKey().

When all put together, the code looks like


import java.util.HashMap;
import java.util.Map.Entry;

public class HashMapTut {
public static void main(String... args) {
HashMap myCoconuts = new HashMap();
myCoconuts.put("Ford",new Coconut(5));
myCoconuts.put("Arthur",new Coconut(2));
myCoconuts.put("Zaphod",new Coconut(3));
myCoconuts.put("Marvin",new Coconut(20));
myCoconuts.put("Trillian",new Coconut(8));

for(Entry cocoEntry:myCoconuts.entrySet()){
System.out.println(String.format("%s - %d", cocoEntry.getKey(),
cocoEntry.getValue().getSize()));
}
}
}


And provides output like:


Ford - 5
Arthur - 2
Marvin - 20
Trillian - 8
Zaphod - 3


Again, the output provided by HashMap is unpredictable, in terms of ordering.


TreeMap


A TreeMap provides much of the same functionality as the HashMap. The TreeMap however will sort the map based on the key values. Again you have the option to provide a comparator into the constructor. If we simply replace the HashMap in the previous example with a TreeMap you will get the following output:


Arthur - 2
Ford - 5
Marvin - 20
Trillian - 8
Zaphod - 3


You can see here that it is sorted by the Key and not the Value.


I hope this has been helpful for you. I tried to give as much information about these main Collection and Map classes as I could without boring you to death. It is very important to know these classes and how to use them, and I now find it very rare to need an array (because ArrayList is so much nicer). Maybe later I'll give them "a flick of the wrist." After all, that's what the show man says.