Unexplainable Singleton / Picocli behaviour - java

I'm writing some code and I can't figure out what's going on with the bug I have. I hope someone here can give me some answers. Here is my code (the relevant part):
public class AppData implements Callable<Integer> {
private static AppData appData = new AppData();
private AppData() {
System.out.println("AppData-Constructor");
}
public static AppData getInstance() {
return appData;
}
#Override
public Integer call() throws Exception { // your business logic goes here...
return 0;
}
private boolean _validate;
public boolean validate() {
return _validate;
}
#Option(names = { "--validate" }, description = "", defaultValue = "false", hidden = false, interactive = false, paramLabel = "", required = false, type = boolean.class)
public void set_validate(boolean validate) {
System.out.println("Set Validate: " + validate);
this._validate = validate;
if(validate)
{
System.out.println("\nBeginne Programmvalidierung\n");
Path tmp = null;
try {
// Doing some validation stuff
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
As you can see my class is a singleton. The annotation is from picoli, which I use to parse the command line arguments. The System.out-calls are for debugging. This is the behaviour I can't explain:
When I start my app with e.g. "-h" as argument, I get the help printed just fine. The System.out.printlnshow that the singleton is created and that set_validate() is called with the default value. But that changes when I use --validate as an argument.
For some reason, the constructor and default set are called twice in a row. After that, set_validate()
is called with true (as it should). However, it seems that the first call sets the static instance variable, while the last call with true is done on the second instance (my theory). As a consequence, when I check the state of _validate with validate() on my singleton instance from my main method (in another class) I get false, as it wasn't set in the right instance.
I used a search engine to check:
The constructor is not called anywhere except for the static singleton instance (as expected, since it's private).
_validate is not accessed anywhere except the code I posted.
set_validate() is not called anywhere. Only Picocli calls it.
I don't know what to check next. Any ideas?
Regards
Thorsten
EDIT:
AppData is one of multiple classes holding the data. They are all collected in one big class for Picocli like this:
class Data
{
#AddGroup(...)
AppData appData = AppData.getInstance();
#AddGroup(...)
FooData fooData = FooData.getInstance();
#AddGroup(...)
BarData barData = BarData.getInstance();
}
It's used like this in my main method:
Data data = new Data();
CommandLine cmd = new CommandLine(data);
cmd.parseArgs(args);

I suspect (but can only guess, since that part of the code is not shown) that AppData is either a subcommand of another command, or that the application uses picocli like this:
int exitCode = new CommandLine(AppData.class).execute(args);
In both cases, picocli will create an instance of AppData using reflection. The instance created by picocli is the instance populated from the command line values. This is a different instance than the one returned by AppData::getInstance.
One way to ensure there is only one instance is to pass the singleton instance to picocli. For example:
AppData singleton = AppData.getInstance();
int exitCode = new CommandLine(singleton).execute(args);
System.out.println("validate=" + singleton.validate());
(If AppData is a subcommand there are other ways to access the instance that picocli created, like the #Spec annotation to inject the picocli model, and calling CommandSpec::userObject() getter on that to get the AppData instance.)
Now, the other question is: why does the set_validate method get invoked twice?
As of version 4.2, picocli will first call #Option-annotated methods with the default value, before parsing the command line parameters. So the set_validate method is first invoked with the default value, and then called again with the value specified on the command line.
(From version 4.3 (to be released soon), the default value will only be set if the value is not specified on the command line, so from version 4.3 the set_validate method will only be invoked once.)

Related

Using a loop to call different methods depending on which string is found

I'm using listeners provided by Pircbotx (https://github.com/pircbotx/pircbotx/wiki/Documentation) to detect when a command is found in Twitch chat, and I am trying to use a different method depending on which Command is called (format is !command). Classes used: Listeners, Command.
Commands are stored in an array of Command objects, comprised of one String (name). Each Command object will ultimately use its own method that will be defined in the Command class. The Listeners object when instantiated will immediately place every element of the array into a hash table (commands).
When Listeners detects a message, it is stored using a local String variable (msg). When this happens, a loop iterates through the Command object array, and then.... is supposed to call the method that corresponds to that particular object, in this case Command.addDeath(). That's where I'm stuck.
I was previously using a bunch of if statements for my listeners, but when there's a bunch of commands things will get really, really messy. Apologies in advance if the formatting in my code block is weird, I'm pretty new to utilizing Stackverflow, and I'm also a Java novice that's learning as I go along. After looking at the code again, it would appear I don't really need the hash table - but I'm leaving it in there just in case you guys have any better ideas for what to do with them.
public class Listeners {
String name;
String message;
private static MessageEvent event;
Command [] commandNames = {new Command("!clearchat", new Command("!addDeath")};
Hashtable<String, Command> commands = new Hashtable<String, Command>();
public Listeners() {
for (int i = 0; i < commandNames.length; i++) {
commands.put(commandNames[i].name, new Command(commandNames[i].name));
}
if (event.getMessage() != null) {
String msg = event.getMessage();
for (int x = 0; x < commandNames.length; x++ ) {
if (msg.startsWith(commandNames[x].name)) {
// call Command method here
}
}
}
}
And here is the Command class:
public class Command {
String name;
public Command(String name) {
this.name = name;
}
public static void addDeath() {
DeathCounter.addDeath();
Listeners.sendMessage("Death Counter: " + DeathCounter.getDeaths());
}
}
You can use an interface for your commands:
public interface Command {
public abstract void execute();
}
Then have your commands implement the interface:
public class DeathCommand implements Command {
#Override
public void execute() {
DeathCounter.addDeath();
Listeners.sendMessage("Death Counter: " + DeathCounter.getDeaths());
}
}
In your listener class, map the command strings to instances of the corresponding command:
public class Listeners {
String name;
String message;
private static MessageEvent event;
static Map<String, Command> commands = new HashMap<>();
static {
commands.put("!addDeath", new DeathCommand());
}
public Listeners() {
if (event.getMessage() != null) {
String msg = event.getMessage();
Optional<String> key = commands.keySet().stream().filter(k -> msg.startsWith(k)).findFirst();
key.ifPresent(s -> commands.get(s).execute());
}
}
}
I replaced your Hashtable with a HashMap which is better in most ways (but is used the same way).
I'm a bit skeptical about having the map as a static member, but since I'm not familiar with your use case I leave that bit as is.
Edit
All Java classes have a default constructor (with no parameters) unless you write your own constructor (you have to write the default one yourself if you still want it). Interfaces don't have constructors since they can't be instantiated directly. They just specify methods that implementing classes must have. This allows you to have references (named fields/variables) of the interface type and be able to call the methods without knowing, or having to know, which implementation it is.
Example:
Command com = new DeathCommand();
com.execute(); // <- this will run the execute() code in the DeathCommand class
Command com2 = new SomeOtherCommand();
com2.execute(); // <- this will run the execute() code in the SomeOtherCommand class
The above code for Command is complete. There is nothing more. As for DeathCommand, and other implementations, you'll need to add what code is needed.
Each class and interface goes in it's own file named as the type:
Command.java
DeathCommand.java
Regarding HashTable vs HashMap. I should have said that it's better to use Map and it's implementations. If you need thread safety, use ConcurrentHashMap as agilob pointed out since regular HashMap is not thread safe.

Groovy method interception on all subtypes

I want to intercept all method calls for Script and any of its subtypes using MetaClasses preferably from Java but if needed I can do it from Groovy. I basically want to do something like this:
MetaClassImpl meta = new MetaClassImpl(Script.class) {
#Override
public final Object invokeMethod(Object obj, String method, Object[] args) {
if(method.equals("evaluate")) {
System.out.println("intercepted");
return run(shell, (String) args[0], "Evaluate");
} else {
return super.invokeMethod(obj, method, args);
}
}
};
The above works fine if I apply it to every instance of Script that I create but I'd like to apply it to the Script class and have it apply to all of its subtypes. Is there any way of doing this?
EDIT: What I'm attempting to do is replace evaluate with another method for all instances of Script and its subtypes. Either that or get evaluate to respect the ImportCustomizer set on the groovy shell the script is running inside of.

arguments for hasPermission in a generic controller

I am trying implement a generic controller class where each method has a structure similar to this:
#RequestMapping(value="cadastra")
#PreAuthorize("hasPermission(#user, 'cadastra_#this.class.name')")
public ModelAndView cadastra() throws InstantiationException, IllegalAccessException {
return new ModelAndView("privado/"+this.entity.getClass().getName()+"/cadastra", "command", this.entity.getClass().newInstance());
}
I am having trouble with the annotation PreAuthorize. the name for the permissionhave this structure: _. right now, I am getting a 403 Error when I try access the view mapped by the method. I also tried other variations like:
#PreAuthorize("hasPermission(#user, 'cadastra_'+#this.class.name)")
or
#PreAuthorize("hasPermission(#user, 'cadastra_#this.getClass().getName()')")
but with the same result. Anyone knows the right way to accomplish this?
UPDATE
I try call this function inside the methods from controller secured by this tag PreAuthorize:
private void expressionParser() {
System.out.println("expressionHandler()");
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("'cadastra_'+#this.class.name");
String message = (String) expression.getValue();
System.out.println("Message is " + message);
}
and when I run the application and open the view should be mapped by a method from controller, like this one:
#RequestMapping(value="cadastra")
#PreAuthorize("hasPermission(#user, 'cadastra_'+#this.class.name)")
public ModelAndView cadastra() throws InstantiationException, IllegalAccessException {
this.expressionParser();
return new ModelAndView("privado/"+this.entityClass.getName()+"/cadastra", "command", this.entityClass.newInstance());
}
No message is displayed on the console. So, I am thinking my application somehow aren't calling the methods from my generic controller. Am I right? If so, how I fix this?
My derived controllers follow this structure:
#Controller
#RequestMapping(value="usuario")
public class UsuarioController extends controller<Usuario> {
public UsuarioController() {
super(Usuario.class);
}
}
So you have difficulties with dynamic construction of permission name in the form of [methodName]_[classFullName] in SpEL expression.
See what SpEL documentation says about #this variable below
The variable #this is always defined and refers to the current evaluation object
(against which unqualified references are resolved).
Based on the documentation and a bit digging in the code the actual object the #this represents should be in your case an instance of org.springframework.security.access.expression.method.MethodSecurityExpressionRoot class. The class contains several helpful methods among others also getThis() method that returns the target object on which the secured method (a method annotated with #PreAuthorize) is being invoked.
Armed with this knowledge it should not be a big deal to construct the expression you require. In case of method named "cadastra", it should be as follows.
#PreAuthorize("hasPermission(#user, 'cadastra_'+#this.this.class.name)")
Hopefully it will also work correctly for secured methods inherited from a base class.
So, I solved this issue with this approach:
1) Adding a new method to my generic controller, where I return the name of the class:
public String getName() {
String expressao = entityClass.getName();
String nome_classe = new String();
StringTokenizer st = new StringTokenizer(expressao, ".");
while (st.hasMoreTokens()) {
nome_classe = st.nextToken();
}
return nome_classe;
}
2) Inside the annotation, I use the returned value by this method and concatenate the result with the constant string (using the notation described by the user #pgjecek in this topic):
#PreAuthorize("hasPermission(#user, 'cadastra_'+#this.this.name)")
and now it1s working perfectly.

By using AspectJ, how can I get 'Object' reference created by 'new' keyword?

Let me directly jump into the example.
public class Target {
public static void main(String[] args) {
Target target = new Target();
Target target2 = new Target();
}
}
I try to capture the Object references(*.hashCode()) by using AspectJ. I prepared code like below:
public aspect ObjectCreationAspect {
before() : initialization(*.new(..)) && !within(ObjectCreationAspect) {
System.out.println();
}
}
I know 'initialization' captures 'new' keyword, but I don't know how can I get the Object itself created by this 'new' keyword. I tried some 'get' methods but they just get only plain name, type(not object), and so forth. What I want is printing values same with target.hashCode() and target1.hashCode() inside this Aspect.
Please give me some hints.
I found an answer.
thisJoinPoint.getTarget().hashCode()
This code will return the reference of newly created object.

CGLIB not able to intercept methods in a superclass/superinterface

May be I'm not thinking hard enough or the answer is really elusive. Quick scenario (Try the code out. It compiles).
Consider a legacy interface
public interface LegacyInterfaceNoCodeAvailable{
void logInfo(String message);
}
The consider a legacy implementation of the interface above
public abstract class LegacyClassNoCodeAvailable implements LegacyInterfaceNoCodeAvailable{
public abstract void executeSomething();
public void rockItOldSchool(){
logInfo("bustin' chops, old-school style");
}
#Override
public void logInfo(String message){
System.out.println(message);
}
}
Now I come in as this ambitious person and writes a class for a 'New' system but that runs inside the 'Legacy' framework, hence I have to extend the legacy base class.
public class lass SpankingShiny extends LegacyClassNoCodeAvailable{
public void executeSomething(){
rockItOldSchool();
logInfo("I'm the King around here now");
System.out.println("this new stuff rocks!!");
}
}
Everything works great, just like you would expect:
SpankingShiny shiny = new SpankingShiny();
shiny.executeSomething();
The above code yields (as expected):
bustin' chops, old-school style
I'm the King around here now
this new stuff rocks!!
Now as you can see, the 'System.out.println()' faithfully prints the desired output. But I wish to replace the 'System.out.println()' with a logger.
Problem:
I'm unable to have the CGLIB proxy intercept the method to 'logInfo(string)' and have it print out my desired message through a logger (I have done the logging configuration right by the way). That method invocation 'apparently' does not hit the proxy.
Code:
public class SpankingShinyProxy implements MethodInterceptor{
private SpankingShiny realShiny;
private final Logger logger = Logger.getLogger(SpankingShinyProxy.class);
public SpankingShinyProxy(SpankingShiny realShiny) {
super();
this.realShiny = realShiny;
}
#Override
public Object intercept(Object proxyObj, Method proxyMethod, Object[] methodParams, MethodProxy methodProxy) throws Throwable {
String methodName = proxyMethod.getName();
if("logInfo".equals(methodName)){
logger.info(methodParams[0]);
}
return proxyMethod.invoke(realShiny, methodParams);
}
public static SpankingShiny createProxy(SpankingShiny realObj){
Enhancer e = new Enhancer();
e.setSuperclass(realObj.getClass());
e.setCallback(new SpankingShinyProxy(realObj));
SpankingShiny proxifiedObj = (SpankingShiny) e.create();
return proxifiedObj;
}
}
Main method:
public static void main(String... args) {
SpankingShiny shiny = new SpankingShiny();
shiny.executeSomething();
SpankingShiny shinyO = SpankingShinyProxy.createProxy(shiny);
shinyO.executeSomething();
}
The above code yields (NOT as expected):
bustin' chops, old-school style
I'm the King around here now
this new stuff rocks!!
bustin' chops, old-school style
I'm the King around here now
this new stuff rocks!!
Where would I be going wrong?
Thanks!
I had the same problem. In my case, the realObj was a proxy itself (a Spring Bean - a #Component).
So what I had to do was change the .setSuperClass() part in:
Enhancer e = new Enhancer();
e.setSuperclass(realObj.getClass());
e.setCallback(new SpankingShinyProxy(realObj));
SpankingShiny proxifiedObj = (SpankingShiny) e.create();
I changed:
e.setSuperclass(realObj.getClass());
To:
e.setSuperclass(realObj.getClass().getSuperClass());
This worked because, as said, realObj.getClass() was a CGLIB proxy itself, and that method returned a crazy-name-CGLIB-generated class, such as a.b.c.MyClass$$EnhancerBySpringCGLIB$$1e18666c. When I added .getSuperClass() it returned the class it should have been returning in the first place.
Well, first of all, you are lucky that your proxy is not hit. If you were referencing the actual proxy within intercept, you would end up with an endless loop since your reflective method incocation would get dispatched by the same SpankingShinyProxy. Again and again.
The proxy is not working since you simply delegate the method call executeSomething on your proxy to some unproxied object. You must not use realObj. All method calls must be dispatched by your proxy, also those method calls that are invoked by the must hit the proxy itself!
Change the last line in your intercept method to methodProxy.invokeSuper(proxyObj, args). Then, construct your object by using the Enhancer. If your constructor for SpankingShiny does not need arguments, calling create without any arguments if fine. Otherwise, supply the objects you would normally supply to the constructor to the create method. Then, only use the object that you get from create and you are good.
If you want more information on cglib, you might want to read this blog article: http://mydailyjava.blogspot.no/2013/11/cglib-missing-manual.html

Categories