I use PicoCLI to parse the arguments. I need to specify setStopAtPositional(true) for one of the subcommands. Is there a way to do this with an annotation? Currently I do this:
cmd.getSubcommands().get("submit").setStopAtPositional(true);
But it would be better to specify it at the method where the submit command is specified to have entire specification in one place.
My class has this structure:
#Command(...)
public class CommandLine implements Callable<Void> {
#Command(...)
public void submit( ... options) {
}
}
Picocli allows different parser configuration for each subcommand, and what you suggest works for your example.
There is currently no annotation API to configure the parser, it may be an idea to add this in a future release.
Note that setting the parser configuration via the CommandLine object will change it for that command and its full hierarchy of subcommands and sub-subcommands.
If you want to change the parser configuration for a single command (without impacting its subcommands), use CommandLine.getCommandSpec().parser() to get its ParserSpec object and do the configuration on that ParserSpec object (example below).
The question did not mention this, but there may be a concern that it's a bit clunky in picocli 3.9.x to invoke the program after configuration, with the parseWithHandler method. This becomes a bit nicer with the execute method added in picocli 4.0.
For example:
#Command(subcommands = B.class)
class A implements Callable<Integer> {
}
#Command(name = "B")
class B implements Callable<Integer> {
#Command
public int subB(... options) {
}
}
public static void main(String... args) {
CommandLine cmdA = new CommandLine(new A());
// Example 1: configure the B command _and_ its subcommands
cmdA.getSubcommands().get("B").setStopAtPositional(true);
// Example 2: configure the A command _only_ (not the subcommands)
cmdA.getCommandSpec().parser().caseInsensitiveEnumValuesAllowed(true);
// parse input and run the command
int exitCode = cmdA.execute(args);
System.exit(exitCode);
}
Related
I came across an interesting article: AOP Aspects as mocks in JUnit
Since I have requirement to mock multiple final and private static variables, I am planning to use AOP in place of reflection or PowerMockito as they are causing issues with SpringJUnit4ClassRunner.
Is there any way I can use #Aspect for test classes without using the annotation #EnableAspectJAutoProxy? (I want to use an aspect targeting class X only in one test case.)
This is a sample of what I want to do.
The question is answered(adding for discussion on what could be done)
//External class
public final class ABC(){
public void method1() throws Exception {}
}
#Service
public void DestClass() {
private static final ABC abc = new ABC();
public Object m() {
// code (...)
try {
abc.method1();
}
catch(Exception e) {
// do something (...)
return null;
}
// more code (...)
}
}
Spring framework allows to programmatically create proxies that advise target objects , without configuring through #EnableAspectJAutoProxy or <aop:aspectj-autoproxy>
Details can be found in the documentation section : Programmatic Creation of #AspectJ Proxies and the implementation is pretty simple.
Example code from the documentation.
// create a factory that can generate a proxy for the given target object
AspectJProxyFactory factory = new AspectJProxyFactory(targetObject);
// add an aspect, the class must be an #AspectJ aspect
// you can call this as many times as you need with different aspects
factory.addAspect(SecurityManager.class);
// you can also add existing aspect instances, the type of the object supplied must be an #AspectJ aspect
factory.addAspect(usageTracker);
// now get the proxy object...
MyInterfaceType proxy = factory.getProxy();
Please note that with Spring AOP , only method executions can be adviced. Excerpt from the documentation
Spring AOP currently supports only method execution join points
(advising the execution of methods on Spring beans). Field
interception is not implemented, although support for field
interception could be added without breaking the core Spring AOP APIs.
If you need to advise field access and update join points, consider a
language such as AspectJ.
The document shared with the question is about aspectj and without providing the sample code to be adviced it is hard to conclude if the requriement can acheived through Spring AOP. The document mentions this as well.
One example of the integration of AspectJ is the Spring framework,
which now can use the AspectJ pointcut language in its own AOP
implementation. Spring’s implementation is not specifically targeted
as a test solution.
Hope this helps.
--- Update : A test case without using AOP ---
Consider the external Class
public class ABCImpl implements ABC{
#Override
public void method1(String example) {
System.out.println("ABC method 1 called :"+example);
}
}
And the DestClass
#Service
public class DestClass {
private static final ABC service = new ABCImpl();
protected ABC abc() throws Exception{
System.out.println("DestClass.abc() called");
return service;
}
public Object m() {
Object obj = new Object();
try {
abc().method1("test");
} catch (Exception e) {
System.out.println("Exception : "+ e.getMessage());
return null;
}
return obj;
}
}
Following test class autowires the DestClass bean with overridden logic to throw exception . This code can be modified to adapt to your requirement.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { DestClassSpringTest.TestConfiguration.class })
public class DestClassSpringTest {
#Configuration
static class TestConfiguration {
#Bean
public DestClass destClass() {
return new DestClass() {
protected ABC abc() throws Exception {
// super.abc(); // not required . added to demo the parent method call
throw new Exception("Custom exception thrown");
}
};
}
}
#Autowired
DestClass cut;
#Test
public void test() {
Object obj = cut.m();
assertNull(obj);
}
}
Following will be the output log
DestClass.abc() called // this will not happen if the parent method call is commented in DestClassSpringTest.TestConfiguration
Exception : Custom exception thrown
The article you are referring to is using full AspectJ, not Spring AOP. Thus, you do not need any #EnableAspectJAutoProxy for that, just
either the AspectJ load-time weaver on the command line when running your test via -javaagent:/path/to/aspectjweaver.jar
or the AspectJ compiler activated when compiling your tests (easily done via AspectJ Maven plugin if you use Maven)
Both approaches are completely independent of Spring, will work in any project and even when using Spring also work when targeting execution of third party code because no dynamic proxies are needed unlike in Spring AOP. So there is no need to make the target code into a Spring bean or to create a wrapper method in your application class for it. When using compile-time weaving you can even avoid weaving into the third party library by using call() instead of execution() pointcut. Spring AOP only knows execution(), AspectJ is more powerful.
By the way: Unfortunately both your question and your comment about the solution you found are somewhat fuzzy and I do not fully understand your requirement. E.g. you talked about mocking final and private static variables, which would also be possible in other ways with AspectJ by using set() and/or get() pointcuts. But actually it seems you do not need to mock the field contents, just stub the results of method calls upon the objects assigned to those fields.
Picocli has to introspect the command tree. Doing so it needs to load the domain object classes for every Command which slows down the jvm startup.
What options are there to avoid this startup lag? One solution I've come up with is described in https://github.com/remkop/picocli/issues/482:
I am using reflection to postpone any class loading until after the command is selected. This way only the command classes themselves are loaded and finally the classes which implement the single command requested by the user:
abstract class BaseCommand implements Runnable {
interface CommandExecutor {
Object doExecute() throws Exception;
}
// find the CommandExecutor declared at the BaseCommand subclass.
protected Object executeReflectively() throws Exception {
Class<?> innerClass = getExecutorInnerClass();
Constructor<?> ctor = innerClass.getDeclaredConstructor(getClass());
CommandExecutor exec = (CommandExecutor) ctor.newInstance(this);
return exec.doExecute();
}
private Class<?> getExecutorInnerClass() throws ClassNotFoundException {
return getClass().getClassLoader().loadClass(getClass().getName() + "$Executor");
}
public void run() {
try {
executeReflectively();
} catch(...){
/// usual stuff
}
}
}
A concrete commend class:
#Command(...)
final class CopyProfile extends BaseCommand {
#Option String source;
#Option String dest;
// class must NOT be static and must be called "Executor"
public class Executor implements CommandExecutor {
#Override
public Object doExecute() throws Exception {
// you can basically wrap your original run() with this boilerplate
// all the CopyProfile's field are in scope!
FileUtils.copy(source, dest);
}
}
}
It seems like https://github.com/remkop/picocli/issues/500 may provide the ultimate solution to this. What are the other options until then?
UPDATE February 2020:
Upgrading to a recent version of picocli should fix this issue.
From the picocli 4.2.0 release notes:
From this release, subcommands are not instantiated until they are matched on the command line. This should improve the startup time for applications with subcommands that do a lot of initialization when they are instantiated.
An alternative that doesn’t require any code changes is to use GraalVM to compile your picocli-based application to a native image.
This article shows how to do this and the resulting startup time is 3 milliseconds.
can anyone tell me what I am doing wrong?
I am wanting to use Mehdime.Entity from https://www.nuget.org/packages/Mehdime.Entity in order to manage my DBContext-derived classes in a Console Application. I am also using NInject.
The connection strings for my DBContext-derived classes are partially generated from standard app.config ConnectionStrings and also by an AppDomain value that (in my Console App case) comes in via a command line argument.
My DBContext-derived classes have their connection strings prepared using a program-implemented class which takes into account of the command line argument as follows:
public class TaskManagementDbContext : DbContext
{
public TaskManagementDbContext(IConnectionStringResolver csr) :
base(csr.GetConnectionString("Default"))
{
}
}
(IConnectionStringResolver basically implements GetConnectionString() which returns the connection string by using given named standard app.config ConnectionString and the command line argument.
This is fine when I use NInject to instantiate the DbContext directly but when trying to use with Mehdime.Entity, it is AmbientDbContextLocator that is doing the instantiation and it throws a MissingMethodException because it requires my DBContext-derived class to have a parameterless constructor:
public class TaskRepository : ITaskRepository
{
private readonly IAmbientDbContextLocator _ambientDbContextLocator;
private TaskManagementDbContext DbContext
{
get
{
// MissingMethodException thrown "No parameterless constructor defined for this object"
var dbContext = _ambientDbContextLocator.Get<TaskManagementDbContext>();
...
}
}
How should I provide a connection string to my DBContext-derived classes at run-time in this situation? I suspect I am going about this the wrong way. Thanks.
OK. I've worked out the solution and I'm putting it here for anyone else with this issue:
Create your own implementation of IDbContextFactory (see below). I put this in the same class library as my Data Access Layer (i.e. my DbContexts). You will see in my example how I "look for" a specific constructor prototype (in my case, 1 parameter of type IDbContextFactory - your's will no doubt be different). If found, get the actual parameters and invoke a new instance of your DBContext-derived class. If not found, you can throw an exception or in my case, try to call the default constructor (if exists).
Code:
using System;
using System.Data.Entity;
using Mehdime.Entity;
using Ninject;
using TaskProcessor.Common;
namespace TaskProcessor.Data.Connection
{
public class DbContextWithCSRFactory : IDbContextFactory
{
public TDbContext CreateDbContext<TDbContext>() where TDbContext : DbContext
{
// Try to locate a constuctor with a single IConnectionStringResolver parameter...
var ci = typeof(TDbContext).GetConstructor(new[] { typeof(IConnectionStringResolver) });
if(ci != null)
{
// Call it with the actual parameter
var param1 = GlobalKernel.Instance.Get<IConnectionStringResolver>();
return (TDbContext)ci.Invoke(new object[] { param1 });
}
// Call parameterless constuctor instead (this is the default of what DbContextScope does)
return (TDbContext)Activator.CreateInstance<TDbContext>();
}
}
}
Create a binding in NInject so that your IDbContextFactory implementation is called:
Code:
private void AddBindings(IKernel kernel)
{ ...
kernel.Bind<IDbContextFactory>().To<Data.Connection.DbContextWithCSRFactory>().InSingletonScope();
}
Everything now falls into place.
I was looking at another question:
Exception is: InvalidOperationException - The current type, is an interface and cannot be constructed. Are you missing a type mapping?
Everyone scolded the person asking the question for 'doing it wrong'. But if you look at all the examples and sites describing this, they all describe injecting an interface into a Controller, typically via the constructor.
The problem here is that suppose I have a Web API which, for example returns a phrase in a different language:
http://mywebapi/api/SayHello/FR
The FR tells the WebAPI that we want Hello in French. I could easily use English, Chinese or any other language.
Now, I decide to build a set of Assemblies, one for each language, all implementing an interface called ILanguage. I make a Unity Container, put named type mappings in the config file (resolving the ILanguage interface with "FR" would return a ILanguage implemented by the French assembly, etc).
The code does NOT know when it's called WHICH implementation it's going to get. Injecting an ILanguage implementation into the Controller constructor seems wrong. Only when the URL is parsed and we get into the method do we see the "FR" parameter passed in, and that tells us to call:
container.Resolve<ILanguage>("FR")
to get the correct ILanguage interface for calling to return the appropriate phrase.
A dogmatic "never call container.Resolve" in your code anywhere, sounds very nice and purist, but it doesn't solve this problem. So, what is the recommended approach? It looks a lot like a ServiceLocator in the sense that we want to find a service dynamically using a 'key' of some kind, but I certainly do NOT want my Web API controller assembly having direct knowledge of all these little language assemblies. I have this working using the system above, but I'm wondering what all the DI/IoC purists would say about this code, and if they don't like it, how they solve the 'dynamic plug-in' problem in a Web API Controller.
I would recommend making your controllers accept a language factory (i.e. a Func<string, ILanguage>) that returns the ILanguage implementation based on the language code you pass into it.
The reason that a factory function should be favored over not declaring any dependencies in your constructor and instead calling container.Resolve() is that the latter obscures the fact that you depend on ILanguage, whereas taking a dependency on a Func<string, ILanguage> makes this very clear.
I.e.:
public interface ILanguage
{
string SayHello();
}
public class Program
{
public static void Main(string[] args)
{
UnityContainer container = new UnityContainer();
container.RegisterType<Func<string, ILanguage>>(new InjectionFactory(con => LanguageFactory));
//Use it:
MyController controller = container.Resolve<MyController>();
string result = controller.TalkToMe("en");
}
private static Func<string, ILanguage> LanguageFactory = delegate(string languageCode)
{
//Create the correct ILanguage here based on the languageCode.
//It's OK to call container.Resolve() here, for example to
//resolve named instances.
return (ILanguage)null;
};
}
public class MyController
{
private Func<string, ILanguage> _languageFactory;
public MyController(Func<string, ILanguage> languageFactory)
{
_languageFactory = languageFactory;
}
public string TalkToMe(string languageCode)
{
ILanguage language = _languageFactory(languageCode);
return language.SayHello();
}
}
As an alternative, you could also use the IUnityContainer that you get passed into the InjectionFactory to do the resolving in the language factory:
container.RegisterType<Func<string, ILanguage>>(new InjectionFactory(con => CreateLanguageFactory(con)));
//...
private static Func<string, ILanguage> CreateLanguageFactory(IUnityContainer container)
{
return delegate(string languageCode)
{
//Create the correct ILanguage here based on the languageCode.
ILanguage result = container.Resolve<ILanguage>(languageCode);
return result;
};
}
How do I call a method of a class dynamically + conditionally?
(Class is eventually not in classpath)
Let's say, I need the class NimbusLookAndFeel, but on some systems it's not available (i.e. OpenJDK-6).
So I must be able to:
Get to know it that class is available (at runtime),
If it's not the case, skip the whole thing.
How do I manage to override a method of a dynamically-loaded class
(thus creating an anonymous inner sub-class of it)?
Code example
public static void setNimbusUI(final IMethod<UIDefaults> method)
throws UnsupportedLookAndFeelException {
// NimbusLookAndFeel may be now available
UIManager.setLookAndFeel(new NimbusLookAndFeel() {
#Override
public UIDefaults getDefaults() {
UIDefaults ret = super.getDefaults();
method.perform(ret);
return ret;
}
});
}
EDIT:
Now I edited my code, as it was suggested, to intercept NoClassDefFoundError using try-catch. It fails. I don't know, if it's OpenJDK's fault. I get InvocationTargetException, caused by NoClassDefFoundError. Funny, that I can't catch InvocationTargetException: It's thrown anyway.
EDIT2::
Cause found: I was wrapping SwingUtilities.invokeAndWait(...) around the tested method, and that very invokeAndWait call throws NoClassDefFoundError when loading Nimbus fails.
EDIT3::
Can anyone please clarify where NoClassDefFoundError can occur at all? Because it seems that it's always the calling method, not the actual method which uses the non-existing class.
Get to know it that class is available (at runtime)
Put the usage in a try block ...
If it's not the case, skip the whole thing
... and leave the catch block empty (code smell?!).
How do I manage to override a method of a dynamically-loaded class
Just do it and make sure the compile-time dependency is satisfied. You are mixing things up here. Overriding takes place at compile time while class loading is a runtime thing.
For completeness, every class you write is dynamically loaded by the runtime environment when it is required.
So your code may look like:
public static void setNimbusUI(final IMethod<UIDefaults> method)
throws UnsupportedLookAndFeelException {
try {
// NimbusLookAndFeel may be now available
UIManager.setLookAndFeel(new NimbusLookAndFeel() {
#Override
public UIDefaults getDefaults() {
final UIDefaults defaults = super.getDefaults();
method.perform(defaults);
return defaults;
}
});
} catch (NoClassDefFoundError e) {
throw new UnsupportedLookAndFeelException(e);
}
}
Use BCEL to generate your dynamic subclass on the fly.
http://jakarta.apache.org/bcel/manual.html
The follow code should solve your problem. The Main class simulates your main class. Class A simulates the base class you want to extend (and you have no control of). Class B is the derived class of class A. Interface C simulates "function pointer" functionality that Java does not have. Let's see the code first...
The following is class A, the class you want to extend, but have no control of:
/* src/packageA/A.java */
package packageA;
public class A {
public A() {
}
public void doSomething(String s) {
System.out.println("This is from packageA.A: " + s);
}
}
The following is class B, the dummy derived class. Notice that, since it extends A, it must import packageA.A and class A must be available at the compile time of class B. A constructor with parameter C is essential, but implementing interface C is optional. If B implements C, you gain the convenience to call the method(s) on an instance of B directly (without reflection). In B.doSomething(), calling super.doSomething() is optional and depends on whether you want so, but calling c.doSomething() is essential (explained below):
/* src/packageB/B.java */
package packageB;
import packageA.A;
import packageC.C;
public class B extends A implements C {
private C c;
public B(C c) {
super();
this.c = c;
}
#Override
public void doSomething(String s) {
super.doSomething(s);
c.doSomething(s);
}
}
The following is the tricky interface C. Just put all the methods you want to override into this interface:
/* src/packageC/C.java */
package packageC;
public interface C {
public void doSomething(String s);
}
The following is the main class:
/* src/Main.java */
import packageC.C;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Main {
public static void main(String[] args) {
doSomethingWithB("Hello");
}
public static void doSomethingWithB(final String t) {
Class classB = null;
try {
Class classA = Class.forName("packageA.A");
classB = Class.forName("packageB.B");
} catch (ClassNotFoundException e) {
System.out.println("packageA.A not found. Go without it!");
}
Constructor constructorB = null;
if (classB != null) {
try {
constructorB = classB.getConstructor(C.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
C objectB = null;
if (constructorB != null) {
try {
objectB = (C) constructorB.newInstance(new C() {
public void doSomething(String s) {
System.out.println("This is from anonymous inner class: " + t);
}
});
} catch (ClassCastException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
if (objectB != null) {
objectB.doSomething("World");
}
}
}
Why does it compile and run?
You can see that in the Main class, only packageC.C is imported, and there is no reference to packageA.A or packageB.B. If there is any, the class loader will throw an exception on platforms that don't have packageA.A when it tries to load one of them.
How does it work?
In the first Class.forName(), it checks whether class A is available on the platform. If it is, ask the class loader to load class B, and store the resulting Class object in classB. Otherwise, ClassNotFoundException is thrown by Class.forName(), and the program goes without class A.
Then, if classB is not null, get the constructor of class B that accepts a single C object as parameter. Store the Constructor object in constructorB.
Then, if constructorB is not null, invoke constructorB.newInstance() to create a B object. Since there is a C object as parameter, you can create an anonymous class that implements interface C and pass the instance as the parameter value. This is just like what you do when you create an anonymous MouseListener.
(In fact, you don't have to separate the above try blocks. It is done so to make it clear what I am doing.)
If you made B implements C, you can cast the B object as a C reference at this time, and then you can call the overridden methods directly (without reflection).
What if class A does not have a "no parameter constructor"?
Just add the required parameters to class B, like public B(int extraParam, C c), and call super(extraParam) instead of super(). When creating the constructorB, also add the extra parameter, like classB.getConstructor(Integer.TYPE, C.class).
What happens to String s and String t?
t is used by the anonymous class directly. When objectB.doSomething("World"); is called, "World" is the s supplied to class B. Since super can't be used in the anonymous class (for obvious reasons), all the code that use super are placed in class B.
What if I want to refer to super multiple times?
Just write a template in B.doSomething() like this:
#Override
public void doSomething(String s) {
super.doSomething1(s);
c.doSomethingAfter1(s);
super.doSomething2(s);
c.doSomethingAfter2(s);
}
Of course, you have to modify interface C to include doSomethingAfter1() and doSomethingAfter2().
How to compile and run the code?
$ mkdir classes
$
$
$
$ javac -cp src -d classes src/Main.java
$ java -cp classes Main
packageA.A not found. Go without it!
$
$
$
$ javac -cp src -d classes src/packageB/B.java
$ java -cp classes Main
This is from packageA.A: World
This is from anonymous inner class: Hello
In the first run, the class packageB.B is not compiled (since Main.java does not have any reference to it). In the second run, the class is explicitly compiled, and thus you get the result you expected.
To help you fitting my solution to your problem, here is a link to the correct way to set the Nimbus Look and Feel:
Nimbus Look and Feel
You can use Class class to do that.
I.E.:
Class c = Class.forName("your.package.YourClass");
The sentence above will throw a ClassNotFoundException if not found on current classpath. If the exception is not thrown, then you can use newInstance() method in c to create objects of your.package.YourClass class. If you need to call a specific constructor, you can use getConstructors method to get one and use it to create a new instance.
Erm, can't you put the class you want to extend into the compile time class path, write your subclass as usual, and at runtime, explicitly trigger loading the subclass, and handle any exception thrown by the linker that indicates that the superclass is missing?