A colleague and I were discussing best practices for managing a Configuration file, and we wanted to get some further feedback from others.
Our goal is for the configuration-file to specify what action should be taken, when certain events occur.
The 2 options that we are debating:
In the config-file, specify the class-path of the class, which implements the action to be taken (eg: "ActionToTake" : "com.company.publish.SendEveryoneAnEmailClass").
Inside the code, when this event is encountered, we can then do Class.forName(config.ActionToTake).newInstance().run() in order to invoke the specified action.
In the config-file, specify in a human-readable-phrase, the action that should be taken (eg: "ActionToTake" : "SendEveryoneAnEmail"). Inside the code, when this event is encountered, we can then parse config.ActionToTake, and perform a mapping that translates this to action implementation (eg: new SendEveryoneAnEmailClass().run())
We are currently a very small team, and the only people reading/using this config file currently, is our team of software devs. But it's unclear if this will continue to be true in future.
Reasoning behind option 1: Anyone reading the config file will explicitly and immediately know what class will get invoked, and where it's implemented. This also allows for the action-class to be implemented/imported from a completely separate JAR file, without recompiling/changing our code.
Reasoning behind option 2: The config file should be a high level description of user-intent, and should not contain implementation details such as specific class names & package paths. Refactoring of class/package names can also be done without having to make config file changes.
Thoughts on which of these 2 design philosophies is preferred for configuration files?
1st option's advantage is, as jas noticed, the ability to 'link' code in the future. It's a real advantage only if you sell/distribute your software as a closed sourced package or if you plan to hot-swap behavior on production. You've already pointed out the cons - refactoring
2nd option:
It won't help you with refactoring. If you change your action from SendEmail to BringBeer but you leave the string send email then you failed.
Readability. send-everyone-an-email is as good as SendEveryoneAnEmail. Every developer will know what will happen. It can't be confused with LaunchRockets. Your code can find class based on some text, not necessarily the full qualified name. Your code can assume that Actions are in some specific package unless explicitly provided. And that is a way to combine both options.
Consider also another possibility: do the configuration in code. If you don't want to recompile the package, you can use scripting language (groovy). It lets you create very readable dsl, and you will have refactoring.
Related
I need to create a map of our domain classes simple names to their fully canonical names. I want to do this only for classes that are under our package structure, and that implement Serializable.
In serialization we use the canonical names of classes alot --it's a good default behaviour as its a very conservative approach, but our model objects are going to move around between packages, and I don't want that to represent a breaking change requiring migration scripts, so I'd like this map. I've already tooled our serializer to use this map, now I just need a good strategy for populating it. Its been frustrating.
First alternative: have each class announce itself statically
the most obvious and most annoying: edit each class in question to include the code
static{
Bootstrapper.classAliases.put(
ThisClass.class.getSimpleName(),
ThisClass.class.getCanonicalName()
);
}
I knew I could do this from the get-go, I started on it, and I really hate it. There's no way this is going to be maintained properly, new classes will be introduced, somebody will forget to add this line, and I'll get myself in trouble.
Second alternative: read through the jar
traverse the jar our application is in, load each class, and see if it should be added to this map. This solution smelled pretty bad -- I'm disturbing the normal loading order and I'm coupled tightly to a particular deployment scheme. Gave up on this fairly quickly.
Third alternative: use java.lang.Instrumentation
requires me to run java with a java agent. More specifics about deployment.
Fourth alternative: hijack class loaders
My first idea was to see if I could add a listener to the class loaders, and then listen for my desired classes being loaded, adding them to this map as they're loaded into the JVM. strictly speaking this isn't doing this statically, but its close enough.
After discovering the tree-like nature of class loaders, and the various different schemes used by the different threads and different libraries, I thought that implementing this solution would be both too complicated and lead to bugs.
Fifth alternative: leverage the build system & a properties file
This one seems like one of the better solutions but I don't have the ant skill to do it. My plan would be to search each file for the pattern
//using human readable regex
[whitespace]* package [whitespace]* com.mycompany [char]*;
[char not 'class']*
class [whitespace]+ (<capture:"className">[nameCharacter]+) [char not '{']* implements [char not '{'] Serializable [char not '{'] '{'
//using notepad++'s regex
\s*package\s+([A-Za-z\._]*);.*class\s+(\w+)\s+implements\s+[\w,_<>\s]*Serializable
and then write out each matching entry in the form [pathFound][className]=[className] to a properties file.
Then I add some fairly simple code to load this properties file into a map at runtime.
am I missing something obvious? Why is this so difficult to do? I know that the lazy nature of java classes means that the language is antithetical to code asking the question "what classes are there", and I guess my problem is a derivative of this question, but still, I'm surprised at how much I'm having to scratch my brain to do this.
So I suppose my question is 2 fold:
how would you go about making this map?
If it would be with your build system, what is the ant code needed to do it? Is this worth converting to gradle for?
Thanks for any help
I would start with your fifth alternative. So, there is a byte code manipulation project called - javassist which lets you load .class files and deal with them using java objects. For example, you can load a "Foo.class" and start asking it things like give me your package, public methods etc.
Checkout the ClassPool & CtClass objects.
List<CtClass> classes = new ArrayList<>();
// Using apache commons I/O you can use a glob pattern to populate ALL_CLASS_FILES_IN_PROJECT
for (File file : ALL_CLASS_FILES_IN_PROJECT) {
ClassPool default = ClassPool.getDefault();
classes.add(default.makeClass(new FileInputStream(file.getPath())));
}
The classes list will have all the classes ready for you to now deal with. You can add this to a static block in some entry point class that always gets loaded.
If this doesn't work for you, the next bet is to use the javaagent to do this. Its not that hard to do it, but it will have some implication on your deployment (the agent lib jar should be made available & the -javaagent added to the startup args).
I have a requirement where I need to put some logic to calculate the rank of some entity (for example a site user eligible for bonus prize). This logic changes very often depending upon the sales, available products, season etc. Also, different installations of the application will have different logic to calculate this rank. I am not sure where should I put this logic. If I put it in java I would have to go for frequent deployments. Getting it through webservice too doesn't looks that promising.
I heard Drools can be used in such scenarios but I have never used it in past. Any help in this regards is highly appreciated.
You should make the classes that implement this logic as decoupled as possible. Use well defined interfaces, and allow each installation to provide it's own implementation if necessary. A Dependency Injection framework, like Spring could be a great help.
Also, consider making your projects in a way that you can deploy independently API and implementation. Maven could help a lot on this.
You can place set of rules in JSON, XML file.
There will be a set of rules.
Your java program will read tags from that file to perform calculations.
For example:
<CalculateBonus>
<minVal>10</minVal>
<maxVal>30</maxVal>
</CalculateBonus>
Then java will read that file containing that rule and get all required data from it:
Int nonPremiumDiscount = 10;//got from file
Int premiumDiscount = 30;//got from file
if(person.isPremiumMember)
{
calculateDiscount(premiumDiscount,price);
}
else
{
calculateDiscount(nonPremiumDiscount,price);
}
If you design your program carefully you will be able to add new rules modify them without or with small change to the code.
That is just idea and would not work for you. But it is exactly what I am doing right now. I have different rules applying to different kind of objects in my code. So for example if I want to validate some additional objects/classes etc (Hope u get what I mean) I just add new rule to my file without even changing a code.
That is really simplified example. In my case I have more than 10 different files having aprox 100 rules each. All of them are in some way connected. So I have rules for general validation but there I include references to other rules in another file:
GeneralValidation -> ValidateEntities -> Something Else
Is there any diff tool specifically for Java that doesn't just highlight differences in a file, but is more complex?
By more complex I mean it'd take 2 input files, the same class file of different versions, and tell me things like:
Field names changed
New methods added
Deleted methods
Methods whose signatures have changed
Methods whose implementations have changed (not interested in any more detail than that)
Done some Googling and can't find anything like this...I figure it could be useful in determining whether or not changes to dependencies would require a rebuild of a particular module.
Thanks in advance
Edit:
I suppose I should clarify:
I'm not bothered about a GUI for the tool, it'd be something I'm interested in calling programmatically.
And as for my reasoning:
To workout if I need to rebuild certain modules/components if their dependencies have changed (which could save us around 1 hour per component)... More detailed explanation but I don't really see it as important.
To be used to analyse changes made to certain components that we are trying to lock down and rely on as being more stable, we are attempting to ensure that only very rarely should method signatures change in a particular component.
You said above that Clirr is what you're looking for.
But for others with slightly differet needs, I'd like to recommend JDiff. Both have pros and cons, but for my needs I ended up using JDiff. I don't think it'll satisfy your last bullet point and it's difficult to call programmatically. What it does do is generate a useful report for API differences.
while migration from weblogic WLI worflow to BPEL Human workflow, what is the option we have for jcx file for interacting with database.
any one please refer any document...
example; in my existing application we are selecting some values from database, in BPEL how we will achieve the same..
I am begineer in BPEL..
I have created a BPEL proces and data adapter inside that, now i want to execute that data adapter from my custom java code, is there any way to do the same.. pelase guide...
thanks
What versions are you working with? It is useful if you add more details about your set up.
Taking a wild guess, here is something that might help you:
Controls are exported as partner-links. The operations for this partner-link are derived from the methods in the control JCX file. Each method parameter is treated as a separate input message part; the name of the part is the same as the name of the parameter. The output message is determined from the return type of the control method. It has a single part called parameters, since a method has a single return type with no name.
http://download.oracle.com/docs/cd/E13214_01/wli/docs85/bpel/export.html#1061022
EDIT:
After a bit of research, I understand that you are on WLI 8.x. The link above should help you if you are facing problems exporting your JPD.
The alternate approach would be to import your 8.x project to 10g3 project, and export it from there. In this approach, you can generate BPEL2.0 compliant workflows. Warning: this is a one-time import, and the project will not be accessible via earlier WLI versions. So, try on a copy.
The second part of your question is not clear. Invoking controls from your Java code would be the same as invoking a web service. The WLI controls that are EJB calls/transformations get converted into web service portTypes. You can consume these web services from your Java application (eg., using Axis.)
Eg: If I am trying to convert a JPD SomeWorkflow.jpd, and if my JPD (WLI 8.x) had a control
/**
* #common:control
*/
private com.appmills.someapp.controls.TestDBCtrl dbctrl;
Or, alternatively with 10g3
#Control()
private com.appmills.someapp.controls.TestDBCtrl dbctrl;
The export creates three files SomeWorkflow.bpel, SomeWorkflow.wsdl and SomeWorkflow_ctrl.wsdl
The generated code would be:
<plnk:partnerLinkType name="com.appmills.someapp.controls.TestDBCtrl">
<plnk:role name="control">
<plnk:portType name="ctrl:com.appmills.someapp.controls.TestDBCtrlPT"
xmlns:ctrl="http://www.bea.com/workshop/bpel/ctrl"/>
</plnk:role>
</plnk:partnerLinkType>
EDIT 2:
The generated WSDL for controls (in the above example SomeWorkflow_ctrl.wsdl) does not contain <binding> or <service> tags. These are left out for you to define. The assumption is that you have these available somewhere, and have to simply wire them in.
As you might be aware of, the JCX equivalents in Oracle-SOA are JCAs. There is no direct export-import between WLI and Oracle-SOA. This means that there could be varying amount of efforts based on your current code complexity and your migration plan.
In my opinion, for JDBC Controls specifically, the simplest solution is to rewrite them as Database adapters.
For example:
Security.setProperty("ocsp.enable", "true");
And this is used only when a CertPathValidator is used. I see two options for imporement:
again singleton, but with getter and setter for each property
an object containing the properties relevant to the current context:
CertPathValidator.setValidatorProperties(..) (it already has a setter for PKIXParameters, which is a good start, but it does not include everything)
Some reasons might be:
setting the properties from the command line - a simple transformer from command-line to default values in the classes suggested above would be trivial
allowing additional custom properties by different providers - they can have public Map getProviderProperties(), or even public Object .. with casting.
I'm curious, because these properties are not always in the most visible place, and instead of seeing them while using the API, you have to go though dozens of google results before (if lucky) getting them. Because - in the first place - you don't always know what exactly you are looking for.
Another fatal drawback I just observed is that this is not thread-safe. For example if two threads want to check a revocation via ocsp, they have to set the ocsp.responderURL property.. and perhaps override the settings of each other.
This is actually a great question that forces you to think about design decisions you may have made in the past. Thanks for asking a question that should have occurred to me years ago!
It sounds like the objection is not so much the singleton aspect of this (although an entirely different discussion could occur about that) - but the use of string keys.
I've worked on APIs that used this sort of scheme, and the reasons you outline above were definitely the driving factors - it makes it crazy simple to parse a command line or properties file, and it allows for 3rd party extensibility without impact to the official API.
In our library, we actually had a class with a bunch of static final String entries for each of the official parameters. This gave us the best of both worlds - the developer could still use code completion where it made sense to do so. It also becomes possible to construct hierarchies of related settings using inner classes.
All that said, I think that the first reason (easy parsing of command line) doesn't really cut it. Creating a reflection driven mechanism for pushing settings into a bunch of setters would be fairly easy, and it would prevent the cruft of String->object transformation from drifting into the main application classes.
Extensibility is a bit trickier, but I think it could still be handled using a reflection driven system. The idea would be to have the main configuration object (the one with all the setters in it) also have a registerExtensionConfiguration(xxx) method. A standard notation (probably dot separated) could be used to dive into the resultant acyclic graph of configuration objects to determine where the setter should be called.
The advantage of the above approach is that it puts all of the command line argument/properties file parsing exception handling in one place. There isn't a risk of a mis-formatted argument floating around for weeks before it gets hit.