How do I determine the main class of a Java application? - java

We are developing a platform, where many developers will be writing their own ETL applications that use a vendor's API that is then submitted for execution onto the platform. We want to constrain developers from just dong their own thing when writing a Main class (that would normally just use the vendor's API), in order to promote some strongly-held conventions. The (large) organisation has a culture of people doing their own thing which over years has resulted in some pretty nasty architecture, so we'd like to impose some best practice conventions that can be enforced by way of CI/CD which will help foster code sharing. The alternative will be a reversion-to-the-norm free for all, which we are desperate to avoid.
How do we determine what the main class of an application is? How can we test for this? We'd like to define either an abstract class or interface that the developers make use of, which will define some up-front promises that the developers must abide by (or else the tests will fail). We can't modify the vendor's code.
So, more concretely, currently we have:
public class MyNastyFreeForAll {
public static void main(String[] ) {
//...
}
}
Is there a way of detecting/enforcing something like:
public class MyConventionEnforcingClass implements/extends MyConventions {
public static void main(String[] ) {
//...
}
}
i.e. test that the main class for the application uses something derived from MyConventions?
Ideally, I want to run the test using Spock.
Alternatively, is there a better way to achieve this aim? Code reviews in an organisation this size amongst lots of separate teams with no central control/hierarchy just isn't going cut it, I'm afraid.
EDIT TO REFLECT INPUT FROM COMMENTS:
At its heart, this is a people problem. However, the people number in their 1000s and cultural change will not happen overnight. It will not happen simply by educating, documenting and influencing and thereby hoping that people will do the right thing. I am looking for a technical solution that can gently steer our developers into doing the right thing - they can always subvert this if they wish, but I want to require them to go out of their way to do so if they want to do this. It is because I am seeking a technical solution that I am posting on SO, not seeking guidance on how to drive cultural change on another site.
EDIT TO PROVIDE MCVE:
Here's an example using an abstract class. It would be nice to validate (at compile or test time) that the main class derives from MyConventions. If a user wants to actively subvert this, then so be it - you can lead a horse to water and all that - but I'm trying to make it easier for end-users to do the right thing than to not do the right thing. Simply giving them a class that does the boilerplate for them is not likely to suffice, as these users like to do their own thing and would likely ignore you, so there should be some form of light-touch technical enforcement. There is no attempt to impose convention on doProcessing() but the same principles could be used to add pre- and post- methods etc to achieve this.
If there is another way of achieving this aim then I'd be very interested in ideas.
// MyNastyFreeForAll.java
// written by end-user
public class MyNastyFreeForAll {
public static void main(String[] args) {
MyNastyFreeForAll entrypoint = new MyNastyFreeForAll();
entrypoint.doBoilerplate();
entrypoint.doProcessing();
}
private void doBoilerplate() {
// lot of setup stuff here, where the user can go astray
// would like to provide this in a class, perhaps
// but we need to be able to enforce that the user uses this class
// and doesn't simply try to roll their own.
System.out.println("Doing boilerplate my own way");
}
private void doProcessing() {
// more things that the user can misuse
System.out.println("Doing doProcessing my way");
}
}
// MyConventions.java
// written by team that knows how to set things up well/correctly
public abstract class MyConventions {
public void doBoilerplate() {
System.out.println("Doing boilerplate the correct way");
}
public abstract void doProcessing();
}
// MyConventionsImpl.java
// written by end-user
public class MyConventionsImpl extends MyConventions {
public static void main(String[] args) {
MyConventions entrypoint = new MyConventionsImpl();
entrypoint.doBoilerplate();
entrypoint.doProcessing();
}
public void doProcessing() {
System.out.println("Doing doProcessing my way");
}
}

You and the other departments can compile all code with the AspectJ compiler, either manually from command line, via batch files, via IDE configured for AspectJ (e.g. Eclipse, IDEA) or via Maven. I created Maven setup for you on GitHub, just clone the project. Sorry, it does not use your MCVE classes because I saw them too late and did not want to start over.
Interface approach
Now let us assume there is an interface which all conforming applications need to implement:
package de.scrum_master.base;
public interface BasicInterface {
void doSomething(String name);
String convert(int number);
}
package de.scrum_master.app;
import de.scrum_master.base.BasicInterface;
public class ApplicationOne implements BasicInterface {
#Override
public void doSomething(String name) {
System.out.println("Doing something with " + name);
}
#Override
public String convert(int number) {
return new Integer(number).toString();
}
public static void main(String[] args) {
System.out.println("BasicInterface implementation");
ApplicationOne application = new ApplicationOne();
application.doSomething("Joe");
System.out.println("Converted number = " + application.convert(11));
}
}
Base class approach
Or alternatively, there is a base class applications have to extend:
package de.scrum_master.base;
public abstract class ApplicationBase {
public abstract void doSomething(String name);
public String convert(int number) {
return ((Integer) number).toString();
}
}
package de.scrum_master.app;
import de.scrum_master.base.ApplicationBase;
public class ApplicationTwo extends ApplicationBase {
#Override
public void doSomething(String name) {
System.out.println("Doing something with " + name);
}
public static void main(String[] args) {
System.out.println("ApplicationBase subclass");
ApplicationTwo application = new ApplicationTwo();
application.doSomething("Joe");
System.out.println("Converted number = " + application.convert(11));
}
}
Unwanted application
And now we have an application which does its own thing, neither implementing the interface nor extending the base class:
package de.scrum_master.app;
public class UnwantedApplication {
public void sayHello(String name) {
System.out.println("Hello " + name);
}
public String transform(int number) {
return new Integer(number).toString();
}
public static void main(String[] args) {
System.out.println("Unwanted application");
UnwantedApplication application = new UnwantedApplication();
application.sayHello("Joe");
System.out.println("Transformed number = " + application.transform(11));
}
}
Contract enforcer aspect
Now let us just write an AspectJ aspect which yields a compiler error via declare error (a warning would also be possible via declare warning, but that would not enforce anything, only report the problem).
package de.scrum_master.aspect;
import de.scrum_master.base.BasicInterface;
import de.scrum_master.base.ApplicationBase;
public aspect ApplicationContractEnforcer {
declare error :
within(de.scrum_master..*) &&
execution(public static void main(String[])) &&
!within(BasicInterface+) &&
!within(ApplicationBase+)
: "Applications with main methods have to implement BasicInterface or extend ApplicationBase";
}
The meaning of this code is: Look for all classes with main methods inside de.scrum_master or any subpackage, but not implementing BasicInterface and not extending ApplicationBase. In reality you would only choose one of the two latter criteria, of course. I am doing both here to give you a choice. If any such class if found, an compiler error with the specified error message is shown.
For whatever reason some people dislike the wonderfully expressive AspectJ native language (a superset of Java syntax) but prefer to write ugly annotation-style aspects, packing all their aspect pointcuts into string constants. This is the same aspect, just in another syntax. Choose any. (In the GitHub project I have deactivated the native aspect by letting is search for the non-existing package xde.scrum_master so as to avoid double compiler errors.)
package de.scrum_master.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareError;
#Aspect
public class ApplicationContractEnforcer2 {
#DeclareError(
"within(de.scrum_master..*) && " +
"execution(public static void main(String[])) && " +
"!within(de.scrum_master.base.BasicInterface+) && " +
"!within(de.scrum_master.base.ApplicationBase+)"
)
static final String errorMessage =
"Applications with main methods have to implement BasicInterface or extend ApplicationBase";
}
Compile with Maven
When running mvn clean compile (see GitHub project for POM), you will see this output (shortened by a bit):
[INFO] ------------------------------------------------------------------------
[INFO] Building AspectJ sample with declare error 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- aspectj-maven-plugin:1.10:compile (default) # aspectj-application-contract-enforcer ---
[INFO] Showing AJC message detail for messages of types: [error, warning, fail]
[ERROR] "Applications with main methods have to implement BasicInterface or extend ApplicationBase"
C:\Users\alexa\Documents\java-src\SO_AJ_EnforceMainClassImplementingInterface\src\main\java\de\scrum_master\app\UnwantedApplication.java:12
public static void main(String[] args) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
Error view in Eclipse
In Eclipse with AJDT (AspectJ Development Tools) it looks like this:
Just rename the main method in UnwantedApplication to something else like mainX and the error goes away.

Related

Design for CLI system that will have a GUI later

Working on a platform that currently has a CLI, but later will have a GUI.
Java.
Basically, currently has a Platform class that orchestrates the interaction of pluggable elements. Platform is a singleton.
There is a CLI class, which has Commands that can use the Platform and its plugins.
Sometimes the Commands employ Platform components (plugins) that require further user interaction (input and output). I am thinking of making a UI interface that Platform is configured with, and the components then make calls out to this to display and obtain input. An event driven solution.
Is that a valid design?
Is there something better?
I am trying to make an MVC style approach work in my head, but the problem is it seems to imply a lot of fore-knowledge in the CLI Commands (ie, the controllers), about the Platform components. That makes them tightly coupled, and I'd like to keep the commands as general as possible. That makes them easier for extenders to work on them, and makes fewer of them for the coming GUI development.
MVC pattern is useful to build the UI (be it CLI, GUI, web page, REST API or something totally different). For integration purposes, you'll want to use other patterns, for instance Facade.
Let's say you're building an ice cream machine. You have a platform interface:
package com.plaform.icecream;
public interface IceCreamMachine {
public void measureCream(int milliLiters);
public void measureCondensedMilk(int milliLiters);
public void measureVanillaExtract(int tableSpoons);
public void measureCacaoPowder(int tableSpoons);
public void mixIngredients();
public void freezeConcoction();
public Object handOverExperimentResults();
}
Then you have your model class of MVC:
package com.cli.icecream.model;
public class Icecream {
private int amount;
private Flavour flavour;
// getters, setters, toString, etc.
}
Flavours as enum:
package com.cli.icecream.model.values;
public enum Flavour {
VANILLA, CHOCOLATE;
}
Controller:
package com.cli.icecream.controller;
public class IceCreamController {
private IceCreamFacade serviceFacade;
public IceCreamController(IceCreamFacade serviceFacade) {
this.serviceFacade = serviceFacade;
}
public void handleShowingFlavours() {
// ...
}
public IceCream handleOrderingIcecream(int balls, Flavour flavour) {
// validations, etc.
return serviceFacade.getIceCream(balls, flavour);
}
}
Now the way to hide the actual details behind the product from the MVC, you can create a Facade that will integrate the two:
package com.cli.icecream.integration;
public interface IceCreamFacade {
public IceCream getIceCream(int balls, Flavour flavour);
}
and:
package com.cli.icecream.integration;
public class IceCreamFacadeImpl {
private IceCreamMachine iceCreamMachine;
public IceCreaFacadeImpl(IceCreamMachine iceCreamMachine) {
this.iceCreamMachine = iceCreamMachine;
}
public IceCream getIceCream(int balls, Flavour flavour) {
int creamMl = ConversionUtil.calculateAmountOfCream(balls);
int condensedMilkMl = ConversionUtil.calculateAmountOfCondensedMilk(balls);
int flavourSubstanceTbsp = ConversionUtil.calculateAmountOfFlavourSubstance(balls);
iceCreamMachine.measureCream(creamMl);
iceCreamMachine.measureCondensedMilk(condensedMilkMl);
switch (flavour) {
case VANILLA:
iceCreamMachine.measureVanillaExtract(flavourSubstanceTbsp);
break;
case CHOCOLATE:
iceCreamMachine.measureCacaoPowder(flavourSubstanceTbsp);
break;
}
mixIngredients();
freezeConcoction();
Object results = iceCreamMachine.handOverExperimentResults();
return ConversionUtil.convertResultsToIceCream(results);
}
}
This way the UI (MVC) consist of classes that are blissfully unaware of how the integrated platform works and vice versa, i.e. decoupled. As an added benefit, if either component changes its behaviour, all your logic to integrate the two are in one place, instead of splattered all over either application.

How to use JUnit4TestAdapter with objects

I am trying to write a test suite using JUnit4 by relying on JUnit4TestAdapter. Having a look at the code of this class I saw that it only works with a Class as input. I would like to build a test class and set a parameter on it before running it with my TestSuite. Unfortunately, Junit4TestAdapter is building the test by using reflection (not 100% sure about the mechanism behind it), which means that I cannot change my test class on runtime.
Has anybody done anything similar before? Is there any possible workaround to this issue? Thanks for your help!
public class SimpleTest {
#Test
public void testBasic() {
TemplateTester tester = new TemplateTester();
ActionIconsTest test = new ActionIconsTest();
test.setParameter("New Param Value");
tester.addTests(test);
tester.run();
}
}
/////
public class TemplateTester {
private TestSuite suite;
public TemplateTester() {
suite = new TestSuite();
}
public void addTests(TemplateTest... tests) {
for (TemplateTest test : tests) {
suite.addTest(new JUnit4TestAdapter(test.getClass()));
}
}
public void run() {
suite.run(new TestResult());
}
}
/////
public interface TemplateTest {
}
/////
public class ActionIconsTest extends BaseTestStrategy implements TemplateTest {
#Test
public void icons() {
//Test logic here
}
public void navigateToTestPage() {
//Here I need the parameter
}
}
/////
public abstract class BaseTestStrategy {
protected String parameter;
#Before
public void init() {
navigateToTestPage();
}
public abstract void navigateToTestPage();
public void setParameter(String parameter) {
this.parameter = parameter;
}
}
I am trying to test a web application with Selenium. The way I want to test is by splitting the functionality, e.g., I want to test the available icons (ActionIconsTest), then I'd like to test other parts like buttons, etc.
The idea behind this is to have a better categorization of the functionality available in certain screen. This is quite coupled with the way we are currently developing our web app.
With this in mind, TemplateTest is just an interface implemented by the different kind of tests (ActionIconTest, ButtonTest, etc) available in my system.
TemplateTester is a Junit suite test with all the different tests that implement the interface TemplateTest.
The reason for this question is because I was trying to implement a Strategy pattern and then realized of the inconvenient of passing a class to Junit4TestAdapter in runtime.
Well, taking in account that JUNIT needs your tester's Class object as an object factory (so he can create several instances of your tester), I can only suggest you pass parameters to your tester through System Properties.
Moreover, it's the recommended way of passing parameters: http://junit.org/faq.html#running_7

org.openide.util.Lookup Cannot Find Any Classes Implementing

SQLUtils.java:
import org.openide.util.Lookup;
import java.util.ServiceLoader; // This doesn't work either
public class SQLUtils {
public static DBDriver getDriver(String prefix) {
for(DBDriver e : Lookup.getDefault().lookupAll(DBDriver.class)) {
System.out.println(e.getPrefix());
if(e.getPrefix().equalsIgnoreCase(prefix)) {
return e;
}
}
return null;
}
}
MySQLDriver.java:
public class MySQLDriver implements DBDriver {
#Override
public String getPrefix() {
return "mysql";
}
}
DBDriver.java:
import java.io.Serializable;
public interface DBDriver extends Serializable {
public String getPrefix();
}
Main.java:
public class Main {
public static void main(String[] args) {
DBDriver d = SQLUtils.getDriver("mysql");
}
}
This does nothing when running it, it cannot find any classes implementing.
What the program is trying to do is get the driver that is entered as a parameter for SQLUtils.getDriver(String prefix) (in Main.java).
For some reason I cannot get this to work.
I'm not familiar with OpenIDE Lookup mechanism, but I am familiar with the Java ServiceLoader mechanism.
You need to provide a file in the META-INF/services/ folder describing what classes implement specific interfaces. From the Java Docs describing the ServiceLoader class is this example:
If com.example.impl.StandardCodecs is an implementation of the
com.example.CodecSet service then its jar file also contains a file
named
META-INF/services/com.example.CodecSet
This file contains the single line:
com.example.impl.StandardCodecs # Standard codecs implementing com.example.CodecSet
What you are missing is a similar file that needs to be included on your classpath or within your JAR file.
You don't include you package names so I cannot provide a more direct example to help solve your problem.
I dropped the NetBeans API and switched to Reflections. I implemented Maven and ran it with IntelliJ. Works well for me.

How to get the Groovy generated java source code

We have some legacy code with Groovy, and we want to remove Groovy from the application, so, we need to get the java source code generated after using the gmaven plug-in.
Basically, in other words I am dynamically generating new classes (using gmaven Groovy maven plug in) and I would like to be able to obtain the java source code of such generated classes.
I researched a little bit and can see that the only goals for this plug in are
<goal>generateStubs</goal>
<goal>compile</goal>
<goal>generateTestStubs</goal>
<goal>testCompile</goal>
I can't see any goal that allows you to obtain the fully implemented java source code, the stub code is not enough for us as we need the final implementation source code in order to get rid of Groovy.
I'm not very familiar with the gmaven plugin, but I assume it compiles the groovy code into byte code. In this case, you can use a byte code decompiler, there is a nice list here. In the past I've used JAD and it was quite nice. The best ones will also try to create meaningful variable names based on class names.
One warning though - Groovy objects are derived from GObject, not java.lang.Object, so you would probably need to keep the groovy jar until the groovy->java porting is done. Also, be prepared that it won't be a very easy to read java...
It may be out of your scope (1 year old) but I fought against the same problem and found a method to retrieve the algorithm (not the java source code) from the decompiled groovy classes.
You may want to take a look : http://michael.laffargue.fr/blog/2013/11/02/decompiling-groovy-made-classes/
The generated stubs will be useless for you. They are just what their names suggests: stubs.
The stubs are only useful when doing joint java/groovy compilation. That's because there are two compilers involved in a java/groovy mixed project.
Parse groovy
Create stubs
Compile java and stubs (using javac)
Continue groovy compilation (using groovyc)
The groovy code will be compiled using groovyc compiler and the result is byte code.
This is an example of a generated stub:
package maba.groovy;
import java.lang.*;
import java.io.*;
import java.net.*;
import java.util.*;
import groovy.lang.*;
import groovy.util.*;
#groovy.util.logging.Log4j() public class Order
extends java.lang.Object implements
groovy.lang.GroovyObject {
public groovy.lang.MetaClass getMetaClass() { return (groovy.lang.MetaClass)null;}
public void setMetaClass(groovy.lang.MetaClass mc) { }
public java.lang.Object invokeMethod(java.lang.String method, java.lang.Object arguments) { return null;}
public java.lang.Object getProperty(java.lang.String property) { return null;}
public void setProperty(java.lang.String property, java.lang.Object value) { }
public int getPrice() { return (int)0;}
public void setPrice(int value) { }
public int getQuantity() { return (int)0;}
public void setQuantity(int value) { }
#java.lang.Override() public java.lang.String toString() { return (java.lang.String)null;}
}
As you can see there is nothing useful. And you will still depend on some groovy libraries.
This question has been on the mailing-list some time ago [0]. To summarize: Groovy to Java is hard to achieve since there are language constructs and APIs (if you do want to totally remove the Groovy dependency) that are not available in Java.
Especially with the introduction of call-site caching and other performance optimizing techniques the generated Java code would look a lot like this (for the matter of simplicity I just threw some script into JD-GUI [1]):
public class script1351632333660 extends Script
{
public script1351632333660()
{
script1351632333660 this;
CallSite[] arrayOfCallSite = $getCallSiteArray();
}
public script1351632333660(Binding arg1)
{
Binding context;
CallSite[] arrayOfCallSite = $getCallSiteArray();
ScriptBytecodeAdapter.invokeMethodOnSuperN($get$$class$groovy$lang$Script(), this, "setBinding", new Object[] { context });
}
public Object run()
{
CallSite[] arrayOfCallSite = $getCallSiteArray(); Object items = ScriptBytecodeAdapter.createList(new Object[0]);
Object[] item = (Object[])ScriptBytecodeAdapter.castToType(ScriptBytecodeAdapter.createList(new Object[] { "Fluff", arrayOfCallSite[1].callConstructor($get$$class$java$util$Date()), (Integer)DefaultTypeTransformation.box(11235813) }), $get$array$$class$java$lang$Object());
arrayOfCallSite[2].call(items, item);
arrayOfCallSite[3].callCurrent(this, items);
ValueRecorder localValueRecorder = new ValueRecorder();
try
{
Object tmp102_101 = items; localValueRecorder.record(tmp102_101, 8);
Object tmp126_121 = arrayOfCallSite[4].call(tmp102_101, new script1351632333660._run_closure1(this)); localValueRecorder.record(tmp126_121, 14); if (DefaultTypeTransformation.booleanUnbox(tmp126_121)) localValueRecorder.clear(); else ScriptBytecodeAdapter.assertFailed(AssertionRenderer.render("assert items.findAll { it }", localValueRecorder), null); } finally {
localValueRecorder.clear(); throw finally; } return null; return null; }
static { __$swapInit();
Long localLong1 = (Long)DefaultTypeTransformation.box(0L);
__timeStamp__239_neverHappen1351632333665 = localLong1.longValue();
Long localLong2 = (Long)DefaultTypeTransformation.box(1351632333665L);
__timeStamp = localLong2.longValue(); }
class _run_closure1 extends Closure implements GeneratedClosure { public _run_closure1(Object _thisObject) { super(_thisObject); }
public Object doCall(Object it) { CallSite[] arrayOfCallSite = $getCallSiteArray(); return it; return null;
}
// ...
[0] http://groovy.329449.n5.nabble.com/Java-lt-gt-Groovy-converters-td337442.html
[1] http://java.decompiler.free.fr

What OO structure should I use to describe animal's behaviors?

I have a Java assignment in which my professor requires me to use a LeJOS NXT to make a robot that simulates a certain animal's behaviors. I chose to develop a dragon. All the possible behaviors that I've come up so far is:
Turning around if it's too close to an obstacle.
Going to sleep when battery is low.
Pushing an object if touches.
If it's too bright, find a dark spot.
etc.
I'm now quite confused because I don't know whether to develop it sequentially in one class or to split all the dragon's behaviors into different classes. Please have a look at my explanation below.
Instead of writing everything inside one class like this:
Dragon.java
public class Dragon {
LightSensor ls = new LightSensor
public static main(String args[]) {
while (!BUTTON.Escape.IsPressed()) {
if (this.closeToObject()) {
this.turnAround();
}
// more conditions
}
}
private boolean closeToObject() {
//TODO
return false;
}
private void turnAround() {
//TODO
}
//... more methods
}
However, I want to make it appears to be more object-oriented as the course is meant to help us gain more OOP skills. So what my second option is to create action classes that extends Dragon's Behavior abstract class like this (roughly):
Dragon.java
public class Dragon {
Detect detect = new Detect(); // carry all the detection methods: distance, sound, etc.
TurnAround turnAround = new TurnAround();
public static main(String args[]) {
while (!BUTTON.Escape.IsPressed()) {
if (detect.tooCloseToObject()) {
turnAround.prepare(); // beep beep alert
turnAround.setDerection(true); // e.g. turn right
turnAround.turn();
}
}
}
}
DragonBehaviors.java
abstract class DragonBehavior {
abstract void prepare();
public void setDirection(boolean direction) {
//...
}
}
TurnAround.java
public class TurnAround extends DragonBehaviors {
String direction;
public void TurnAround() {}
public void prepare() {
// sound alert
}
public void setDirection(boolean direction) {
if (direction) this.direction = "Right";
else this.direction = "Left";
}
public void turn() {
// TODO
}
}
The code above is roughly a draft, don't focus on it. Eventually, I want to ask if my idea about the OO structure above is reasonable, otherwise it's much easier to develop the whole thing in one class, but it has nothing to do with OOP. I also have several group members to make the code finished, so I think it could be better if we share the classes to develop in an OOP way.
Which way should I go in this circumstance?
I appreciate all the comments (:
Your choice of extracting different actions into classes with common super class is IMHO reasonable. However I would make Dragon class only aware of the DragonBehavior abstract class, not the subclasses. This way you can add and remove behaviours to the dragon without actually changing it.
How? Look at Chain-of-responsibility pattern - each behaviour has its place in the chain. If behaviour decides to activate itself (i.e. perform something) it may or may not allow further behaviours to be triggered. Moreover, you can and remove behaviours (even at runtime!) and rearrange them to change the precedence (is pushing the obstacle more or less important than going to sleep?).

Categories