I have a java file as follows
package sample;
public class Profile
{
public static String myName(String name)
{
myhobby("Football");
return name;
}
public static String myhobby(String hobby)
{
return hobby;
}
}
I build this file and added the jar file into the below code...
import sample.Profile;
public class Hello
{
public static String sayHello(String name)
{
String enter=Test.myName("Ganguly");
return name;
}
public static void main(String[] args)
{
String next = sayHello("Company");
}
}
And I wrote aspect as follows...
pointcut printMessage(String name) : call(public static String myhobby(..)) && args (name));
before(String name) : printMessage(name) {
System.out.println("value is: "+ name);
}
But when I run the program...it doesn't printed the parameter value of the function hobby...
can any one correct me if I am wrong...
Thanks in advance...
By default, AspectJ IDE only weave current project with aspects of same project, we need add In-Path or Aspect-Path for the project for other scenarios.
From Properties dialog of the second project (your testing project) > 'AspectJ Build' page > InPath , add your jar to the list (the jar is added to Java Build Path library automatically at same time).
Related
Like spigot/bukkit plugins id like to be able to load jars in a file and load their classes. Ive managed to get this working with java class loader but the class has to extend a runnable for it to work. Id like to have my own custom interface to implement for each plugin(jar). So I could have functions that get ran on plugin load and so on. If anyone knows how to do this please let me know.
Plugin structure
A plugin is a .jar file. The plugin has a plugin.properties file with the properties of the plugin.
It looks like this:
plugin.main=com.example.plugins.ExamplePlugin
plugin.name=Example Plugin
plugin.description=Test 123
plugin.version=1.0
The file contains the main class, the plugin name, a description and the version.
A plugin must have a class that inherits from the abstract plugin class. This counts as the main class.
Code structure
Let's begin with the Plugin-class:
package com.example.plugins;
public abstract class Plugin {
protected PluginProperty property;
public abstract void onEnable();
public abstract void onDisable();
public PluginProperty getProperty() {
return property;
}
public void setProperty(PluginProperty property) {
this.property = property;
}
}
As you may see, I have chosen an abstract class here.
The class consists of two abstract methods (onEnable and onDisable). The plugin also has a PluginProperty object. The equivalent of this class in Spigot would be JavaPlugin.
Let's take a look at the PluginProperty class.
package com.example.plugins;
public class PluginProperty {
private String main;
private String name;
private String description;
private double version;
public PluginProperty(String main, String name, String description, double version) {
this.main = main;
this.name = name;
this.description = description;
this.version = version;
}
public String getMain() {
return main;
}
public void setMain(String main) {
this.main = main;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public double getVersion() {
return version;
}
public void setVersion(double version) {
this.version = version;
}
}
This class has all the necessary properties of a plugin in it. Most of the things here are self-explanatory, but I would still like to discuss main.
The string holds the name of the main plugin class of the plugin. This is basically the same as the main in the plugin.yml in Spigot.
The loader
Here is the PluginLoader-class:
package com.example.plugins;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Properties;
import java.util.zip.ZipException;
public class PluginLoader {
private static PluginProperty loadPluginProperties(File file) throws ZipException, IOException {
URL url = file.toURI().toURL();
String jarURL = "jar:" + url +"!/plugin.properties";
InputStream input;
URL inputURL = new URL(jarURL);
JarURLConnection conn = (JarURLConnection)inputURL.openConnection();
input = conn.getInputStream();
Properties property = new Properties();
property.load(input);
String main = property.getProperty("plugin.main");
String name = property.getProperty("plugin.name");
String description = property.getProperty("description");
double version = Double.parseDouble(property.getProperty("plugin.version"));
return new PluginProperty(main, name, description, version);
}
public static Plugin loadPlugin(File file) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
if(!file.exists()) {
return null;
}
PluginProperty property = loadPluginProperties(file);
URL url = file.toURI().toURL();
String jarURL = "jar:" + url + "!/";
URL urls[] = {new URL(jarURL)};
URLClassLoader ucl = new URLClassLoader(urls);
Plugin plugin = (Plugin) Class.forName(property.getMain(), true, ucl).getDeclaredConstructor().newInstance();
plugin.setProperty(property);
return plugin;
}
}
The private loadPluginProperties method loads the plugin properties and returns the required object. The loadPlugin method loads the main class specified in the properties into an object and returns it.
Examples
I just gave you the basic framework for the plugin system. But how should you use it? Let's start with an example loader.
Here is the Main-class:
package com.example.plugins;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static List<Plugin> plugins = new ArrayList<Plugin>();
public static void main(String[] args) {
File[] pluginFiles = new File("plugins").listFiles();
//Load plugins
for(File f : pluginFiles) {
if(f.isDirectory()) {
continue;
}
if(!f.getName().endsWith(".jar")) {
continue;
}
Plugin p = null;
try {
p = PluginLoader.loadPlugin(f);
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | IOException e) {
System.err.println("Failed to load plugin!");
e.printStackTrace();
}
Main.plugins.add(p);
}
//Enable plugins
for(Plugin p : plugins) {
p.onEnable();
}
//Disable plugins
for(Plugin p : plugins) {
p.onDisable();
}
}
}
I won't go into much detail here as I think it's pretty self-explanatory. If you have a question, just ask me through the comments.
After exporting the previously written as a JAR, add it to the classpath in a new project. Don't forget to create a plugin.properties file.
This is an example plugin that is compatible with the .properties file specified above:
package com.example.plugins;
public class ExamplePlugin extends Plugin {
#Override
public void onEnable() {
System.out.println("Hello world!");
}
#Override
public void onDisable() {
}
}
When I export this plugin and put it in the plugins folder I get the following output:
Hello world!
The End
It would be recommended to use JSON or YAML, XML etc. instead of the built-in Java property files. This is the basic structure for plugins. Have fun!
Here is the project architecture:
Here is the Car class that won't compile:
package car;
import engine.Engine;
public class Car {
private Engine engine;
/***
* Constructor
* #param engine The engine that the car object will have
*/
Car(Engine engine) {
engine = new Engine(engine); // Use the Engine copy constructor
}
}
Here is the error:
Here is the Engine class in the engine package:
package engine;
public class Engine {
private String name;
private int displacement;
public Engine(String name, int displacement) throws Exception {
setName(name);
setDisplacement(displacement);
}
public String getName() {return name;}
public int getDisplacement() {return displacement;}
private void setName(String name) throws Exception {
if (name.trim().length() == 0) {
throw new Exception("Engine name cannot be blank");
}
}
private void setDisplacement(int displacement) throws Exception {
if (displacement < 0) {
throw new Exception("Engine displacement cannot be zero or negative");
}
}
}
Try cleaning the project in Project --> clean
Fixed: I didn't change the code, I deleted the project from the workspace, closed Eclipse, reopened Eclipse with a different workspace, and imported the same project into the workspace. Arrrgh.
My code is exactly the same as the example shown on py4j website:
Implementing Java Interfaces from Python
Except my classes are all in the same src.main.java package
(see below for the code)
Problem:
If I do a gradle fatjar build with ListenerApplication as main, then execute the jar, everything works fine. If I do a gradle fatjar build and instead access the code via a plugin interface, I get the following error:
Py4JError: An error occurred while calling o0.registerListener. Trace:
py4j.Py4JException: Invalid interface name: ExampleListener
at py4j.Protocol.getPythonProxy(Protocol.java:429)
at py4j.Protocol.getObject(Protocol.java:311)
at py4j.commands.AbstractCommand.getArguments(AbstractCommand.java:82)
at py4j.commands.CallCommand.execute(CallCommand.java:77)
at py4j.GatewayConnection.run(GatewayConnection.java:238)
at java.lang.Thread.run(Thread.java:748)
Question: Why does Py4J have problems finding "ExampleListener" when the .jar is run as a plugin and not as an application? I can even add :
public String classtest() throws Exception {
System.out.println("classtest called");
Class<?> py = Class.forName("ExampleListener");
return py.toString();
}
to the ListenerApplication, which will return the correct interface both when run as plugin and as application! The interesting thing is, if I run the program plus plugin from netbeans IDE, everything works fine! Does Netbeans somehow expose the interface, while the application run directly, does not?
Plugin interface
import org.micromanager.MenuPlugin;
import org.micromanager.Studio;
import org.scijava.plugin.Plugin;
import org.scijava.plugin.SciJavaPlugin;
import py4j.GatewayServer;
#Plugin(type = MenuPlugin.class)
public class Py4JPluginInterface implements MenuPlugin, SciJavaPlugin{
private static final String menuName = "Simpletest_gradle";
private static final String tooltipDescription = "py4j gateway";
private static final String version = "0.1";
private static final String copyright = "copyright";
#Override
public String getSubMenu() {
return "Simpletest_gradle";
}
#Override
public void onPluginSelected() {
GatewayServer gatewayServer = new GatewayServer(new ListenerApplication());
gatewayServer.start();
System.out.println("Gateway Started at IP:port = "+gatewayServer.getAddress()+":"+gatewayServer.getPort());
}
#Override
public void setContext(Studio app) {
}
#Override
public String getName() {
return menuName;
}
#Override
public String getHelpText() {
return tooltipDescription;
}
#Override
public String getVersion() {
return version;
}
#Override
public String getCopyright() {
return copyright;
}
}
The interface:
//py4j/examples/ExampleListener.java
package py4j.examples;
public interface ExampleListener {
Object notify(Object source);
}
The application:
package py4j.examples;
import py4j.GatewayServer;
import java.util.ArrayList;
import java.util.List;
public class ListenerApplication {
List<ExampleListener> listeners = new ArrayList<ExampleListener>();
public void registerListener(ExampleListener listener) {
listeners.add(listener);
}
public void notifyAllListeners() {
for (ExampleListener listener: listeners) {
Object returnValue = listener.notify(this);
System.out.println(returnValue);
}
}
#Override
public String toString() {
return "<ListenerApplication> instance";
}
public static void main(String[] args) {
ListenerApplication application = new ListenerApplication();
GatewayServer server = new GatewayServer(application);
server.start(true);
}
}
The python listener
from py4j.java_gateway import JavaGateway, CallbackServerParameters
class PythonListener(object):
def __init__(self, gateway):
self.gateway = gateway
def notify(self, obj):
print("Notified by Java")
print(obj)
gateway.jvm.System.out.println("Hello from python!")
return "A Return Value"
class Java:
implements = ["py4j.examples.ExampleListener"]
if __name__ == "__main__":
gateway = JavaGateway(
callback_server_parameters=CallbackServerParameters())
listener = PythonListener(gateway)
gateway.entry_point.registerListener(listener)
gateway.entry_point.notifyAllListeners()
gateway.shutdown()
For those who are interested, this was a class loader issue, which is apparently common for plugin/OSGI apps.
See the maintainer's response:
https://github.com/bartdag/py4j/issues/339#issuecomment-473655738
I simply added the following to the Java-side ListenerApplication constructor:
RootClassLoadingStrategy rmmClassLoader = new RootClassLoadingStrategy();
ReflectionUtil.setClassLoadingStrategy(rmmClassLoader);
Hello java programmers,
I have a problem with reading the properties file based on active profile. I have created a spring boot application and I would like to deploy my application for different environments such as development and production. I have searched quit a lot, but I could not find a solution for my problem.
I have set a profile in the edit configuration menu.
I have a properties file called application-dev.properties in my src/main/resources and I have a Settings.java where I would like to read the properties file.
This is my Settings.java
#Configuration
#Component
public class Settings {
private static Logger log = Logger.getLogger(Settings.class);
#Value("${TradingBot.production}")
public boolean isProduction;
#Value("${api.KEY}")
public static String API_KEY;
#Value("${api.ORDERS_URL}")
public static String ORDERS_URL;
#Value("${api.TRADES_URL}")
public static String TRADES_URL;
#Value("${api.PARTICIPANTS_URL}")
public static String PARTICIPANTS_URL;
#Value("${api.INDIVIDUAL_URL}")
public static String INDIVIDUAL_URL;
#Value("${api.BALANCE_URL}")
public static String BALANCE_URL;
#Value("${api.TRANSACTIONS_URL}")
public static String TRANSACTIONS_URL;
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){
return new PropertySourcesPlaceholderConfigurer();
}
}
According to the spring documentation this should be enough to read the correct properties file, unfortunately I get an empty String when I print the value.
When I run the project it will give me the following output.
2016-10-31 13:44:04.011 INFO 32992 --- [ main] TradingBot : The following profiles are active: dev
I hope someone can help me.
Thanks to M.Denium I knew what the problem was. I could solve it by adding the #Value property at the setter for Example:
public static String API_KEY;
public static String ORDERS_URL;
public static String TRADES_URL;
public static String PARTICIPANTS_URL;
public static String INDIVIDUAL_URL;
public static String BALANCE_URL;
public static String TRANSACTIONS_URL;
#Value("${api.KEY}")
public void setAPI_KEY(String API_KEY) {
this.API_KEY = API_KEY;
}
#Value("${api.ORDERS_URL}")
public void setORDERS_URL(String ORDERS_URL) {
this.ORDERS_URL = ORDERS_URL;
}
#Value("${api.TRADES_URL}")
public void setTRADES_URL(String TRADES_URL) {
this.TRADES_URL = TRADES_URL;
}
#Value("${api.PARTICIPANTS_URL}")
public void setPARTICIPANTS_URL(String PARTICIPANTS_URL) {
this.PARTICIPANTS_URL = PARTICIPANTS_URL;
}
#Value("${api.INDIVIDUAL_URL}")
public void setINDIVIDUAL_URL(String INDIVIDUAL_URL) {
this.INDIVIDUAL_URL = INDIVIDUAL_URL;
}
#Value("${api.BALANCE_URL}")
public void setBALANCE_URL(String BALANCE_URL) {
this.BALANCE_URL = BALANCE_URL;
}
#Value("${api.TRANSACTIONS_URL}")
public void setTRANSACTIONS_URL(String TRANSACTIONS_URL) {
this.TRANSACTIONS_URL = TRANSACTIONS_URL;
}
In this case the variable will still be static and it can get the value from the property file.
Hello I have a simple testNG project which has a SampleTest.java class file which has 2 test cases and I have added a listener called MyListener to it . For this I have a MyListener.java class file which extends the TestListener of TestNG where in I'm printing pass or fail or skipped depending upon the test case execution. So every time i run SampleTest I can see Pass/fail in the console.. But I want it with the classname
My problem statement is, How can i get the Test Case file name (i.e. Sampletest here) in the MyListener class??? I tried with stacktrace but no help.. As I guess its not being called but its just acting upon/listening to the testcases in the file.. Please let me know how can I get the name of that class in listener????
SampleTest.java:
package com.abc;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
#Listeners({ com.mindtree.MyListener.class})
public class SampleTest {
#Test
public void SampleTest() throws Exception{
System.out.println("Hello world");
}
#Test
public void SampleTest1() throws Exception{
System.out.println("Hello Swarna");
}
}
MyListener.java:
package com.abc;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;
public class MyListener extends TestListenerAdapter {
private int m_count = 0;
#Override
public void onTestFailure(ITestResult tr) {
log("Fail");
}
#Override
public void onTestSkipped(ITestResult tr) {
log("Skipped");
}
#Override
public void onTestSuccess(ITestResult tr) {
log("\nSuccess\n");
## WANT TO PRINT HERE THE TESTCASE CLASS NAME
}
private void log(String string) {
System.out.print(string);
if (++m_count % 40 == 0) {
System.out.println("");
}
}
}
but wont work for multiple testcase files.. Just create an object of SampleTest in MyListener access the classname through getters and setters
From your description I understand you want to get the name of the class where your #Test annotated test-methods reside, and only the class name without the package name
In your case that would be the output: "SampleTest".
You can achieve this the following way:
public void onTestSuccess(ITestResult tr) {
log("\nSuccess\n");
String className = tr.getTestClass().getRealClass().getSimpleName()
log(className);
}
The solution of #JacekM also works fine but in your case would return "com.abc.SampleTest"
None of the solution posted worked for me, however I found that it is possible to get the required information by accessing the "ITestResult" object in the following manner:
public void onTestSuccess(ITestResult result) {
log("\nSuccess\n");
String className = result.getInstanceName();
log(className);
}
NOTE: The above code was tested on my environment successfully
You can find out by examining the stacktrace like:
StackTraceElement trace[] = Thread.currentThread().getStackTrace();
you can get the the calling class by trace[i].getClassName().
Note this is pretty expensive, so don't use in loggers etc.
Use a beforeMethod method in which you can get the name of the method
#BeforeMethod
public void beforeMethod(final Method method) throws Exception {
String testName = method.getName();
}
You have the access to ITestResult object, so you should be able to do:
public void onTestSuccess(ITestResult tr) {
String className = tr.getMethod().getTestClass().getName();
System.out.println(className);
}