How to run ajc from Java? - java

I'm trying to run ajc compiler from Java (not from Maven or Ant!). The question is which Maven dependency do I need and which class is an entry point? The best option I have now is org.aspectj.tools.ajc.Main from org.aspectj:aspectjtools:1.7.2. Am I right?

Yes. In your Java project you need aspectjrt.jar (for the runtime) and aspectjtools.jar (for the compiler) on the class path. Then you can build an AspectJ project and create a JAR file containing aspects and classes like this:
import org.aspectj.tools.ajc.Main;
public class AjcRunner {
public static void main(String[] args) throws Exception {
String[] ajcArgs = {
"-sourceroots", "c:\\my\\aspectj_project\\src",
"-outjar", "my_aspects.jar"
};
Main.main(ajcArgs);
}
}
Afterwards you can test the result on the console like this, assuming you have a class Application with a main method:
java -cp C:\path\to\aspectjrt.jar;my_aspects.jar Application

Related

Error: Package doesn't exists when importing a user defined package from a class

Here My first file code
package com.shubham.packages.a;
import static com.shubham.packages.b.Message.Hello;
public class Greeting {
public static void main(String[] args) {
System.out.println("Hello World");
Hello();
}
}
Here my second file code
package com.shubham.packages.b;
public class Message {
public static void main(String[] args) {
}
public static void Hello() {
System.out.println("This is Awesome.");
}
}
Here the error I got when I run the program.
When you compile your code javac needs to know where to look for all of your source/class files. You could go to "java_tutorial" folder and run.
javac com/shubham/packages/a/Greeting.java com/shubham/packages/b/Message.java
That should compile both of your java files into class files at the same location. Then you should be able to run.
java com.shubham.packages.a.Greeting
I might be using the wrong slashes for windows
You can explicitly name all of the necessary java files, so this should cause both Greeting.java and Message.java to be compiled in place.
When you run java, the CWD is on the classpath by default so that means the package com.shubham.packages.a and ...b should be on the classpath in their correct location.
A slightly better way to do this is to create a folder called "build" or whatever you like.
javac -d build com/shubham/packages/a/Greeting.java com/shubham/packages/b/Message.java
That will output the class files to the build folder. Then when you run it.
java -cp build com.shubham.packages.a.Greeting

Write Unit Test In Different Package Calling Private/Protected Methods Using Intellij

I realize this question has been asked before here -> How to create a test directory in Intellij 13?
However, the answer is not working for me and I can't figure out why...
Intellij Version:
IntelliJ IDEA 2016.1.4
Build #IC-145.2070, built on August 2, 2016
JRE: 1.8.0_77-b03 x86
JVM: Java HotSpot(TM) Server VM by Oracle Corporation
MyApp.java
package main.java.com.simpleproject;
public class MyApp {
private int updNum;
public MyApp(int givenNum){
this.updNum = givenNum;
}
private void updateNumPlusTwo(){
this.updNum += 2;
}
protected int getUpdatedNum(){
return this.updNum;
}
}
MyAppTest.java
package test.java.com.simpleproject;
import main.java.com.simpleproject.MyApp;
public class MyAppTest {
public static void main(String[] args) {
MyApp app = new MyApp(4);
app.getUpdatedNum();
app.updateNumPlusTwo();
}
}
The package/directory tree:
The Issue:
What I have tried:
Anyone have any idea how to get this to work?
Your sources directories and packages are wrong.
You have chosen the Maven default sources directories structure of src/main/java for production code, and src/test/java for test code. You should declare both directories as source folders in IntelliJ (Project Structure -> Modules -> select the folders and click on Sources for src/main/java and Tests for src/test/java)
Your packages should be the same: com.simpleproject. The problem is that you have declared 2 different packages (main.java.com.simpleproject and test.java.com.simpleproject) that's why you cannot call a protected method.
It is not possible to call a private method, from the same or different package. You have to use reflection for that. But preferably you should at least put your method protected or package default.
Your test should use JUnit, not a main method. Something like :
package com.simpleproject;
import static org.assertj.core.api.Assertions.assertThat;
public class Test {
#Test
public void shouldTestMyClass() {
// Given
int givenNum = 3;
// When
MyApp myApp = new MyApp(givenNum);
myApp.updateNumPlusTwo();
// Then (use AssertJ library for example)
assertThat(myApp.getUpdatedNum()).isEqualTo(5);
}
}

How to start Vert.x server from IntelliJ IDEA?

How do I start a simple Vert.x server from inside IntelliJ IDEA?
My build.gradle is as below:
apply plugin: 'java'
version = '3.0.0'
repositories {
mavenCentral()
}
dependencies {
compile 'io.vertx:vertx-core:3.0.0'
}
My Vertx-server, MyVertex.java is as below:
package com.example;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
public class MyVerticle extends AbstractVerticle {
#Override
public void start(Future<Void> fut) {
vertx.createHttpServer()
.requestHandler(r -> r.response().end("<h1>Hello</h1>"))
.listen(8081);
}
}
And my IntelliJ run configuration is as below, with io.vertx.core.Starteras main class:
But when I run it with my run configuration I get this error message:
Error: Could not find or load main class run
Is the VM option (in Run configuration) run something I need to install and add to my path or how do I get started with Vert.x-server development?
I'm using vertx 3.2.1 and it's complaining about io.vertx.core.Starter. It's deprecated now. So, one should use io.vertx.core.Launcher.
This is an example of launching via intellij with the option of specifying a config JSON file:
Main Class: io.vertx.core.Launcher
VM Options: <up to you, or leave blank>
Program Arguments: run com.app.verticle.MyVerticle -conf /path/to/my_config.json
When using a logging framework it will be added in VM Options as below.
Log4j with either log4j or slf4j delgate:
-Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.Log4jLogDelegateFactory -Dlog4j.configuration=log4j.xml
-Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory -Dlog4j.configuration=log4j.xml
Logback:
-Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory -Dlogback.configurationFile=logback.xml
Simply add this to your MyVerticle (or a separate class):
import io.vertx.core.Launcher;
...
public static void main(final String[] args) {
Launcher.executeCommand("run", MyVerticle.class.getName());
}
Then simply Ctrl+Shift+F10 to run it and IntelliJ will automatically create the Run Configuration.
Ah, my mistake:
run com.example.MyVerticle should be the value of Program arguments: and not as VM options in the IntelliJ IDEA Run configuration.
You can simply add a main and use deployVerticle() and then from there in IntelliJ you can Run or Debug it easily.
With deployVerticle, you can pass a new instance of your main/bootstrap verticle or you can pass yourMainVerticle.class
public class VertxVerticleMain {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new MyVerticle());
//vertx.deployVerticle(MyVerticle.class);
}
}
You have to use this: org.vertx.java.platform.impl.cli.Starter as your Main Class in IntelliJ IDEA; and if you are using arguments and things like that you might want to use something like: runmod <groupId>~<artifactId>~<version> [-conf src/main/resources/your_config.json -cp]
Have a look at this project.
For Vert.x 3.0.0 you have to use this: io.vertx.core.Starter as your Main Class and run com.example.other.AnyVerticle as your Program arguments.

Create API in Groovy for Java

I'm need to create an api for what will be a suite of primarily java applications. I need to do this quickly however, and at the moment I'm most comfortable writing in groovy. My question is, can I create this api in groovy, and use it in java applications without any special hoops?
That is, can I create a jar from my groovy classes and methods, and have the java applications use this jar as though it were created in java?
Yes, you can. Just compile using gradle, ant, whatever, to generate a jar. The resulting jar will depend on Groovy runtime jar and modules, if any. Groovy compiles to bytecode, so Java doesn't really know the differente. Only dynamic stuff won't work.
MyLib.groovy:
class MyLib {
def string
MyLib(string) {
this.string = string
}
String yell() {
string.toUpperCase() + "!!!"
}
}
Compiled:
$ groovyc MyLib.groovy
Writing the Java class which uses the Groovy one, TestMyLib.java:
public class TestMyLib {
public static void main(String[] args ) {
MyLib my = new MyLib("john doe");
System.out.println(my.yell()); // prints JOHN DOE!!!
}
}
Compiling:
$ javac TestMyLib.java
And execution:
$ java -cp $GROOVY_HOME/embeddable/groovy-all-2.1.8.jar:. TestMyLib
JOHN DOE!!!

Java SPI JARs not loaded from directory without setting -Djava.ext.dirs

I can't get the Service Provider Interface to load an implementation from another JAR in the same directory. It only works when I use -Djava.ext.dirs=. on the command line. Should it not work without?
I have the following interface:
package playground;
public interface TestIface {
public String test();
}
which is implemented here:
package playground;
public class TestImpl implements TestIface {
public String test() {
return "TEST";
}
}
Here I try to load the implementation:
package playground;
import java.util.Iterator;
import java.util.ServiceLoader;
public class Lalala {
public static void main(String[] args) {
ServiceLoader<TestIface> loader = ServiceLoader.load(TestIface.class);
Iterator<TestIface> it = loader.iterator();
while (it.hasNext()) {
TestIface a = it.next();
System.out.println(a.test());
}
System.out.println("DONE");
}
}
The interface and the last class are packaged in main.jar, the implementation in impl.jar.
main.jar has the Main class set and impl.jar has the META-INF/services/playground.TestIface file which contains "playground.TestImpl". Both JARs are in the same directory.
Running
java -jar main.jar
only prints "DONE", the implementation apparently is not found.
If I instead run
java -Djava.ext.dirs=. -jar main.jar
it also prints "TEST" as it should.
What am I doing wrong? Why is the implementation from the other JAR not loaded unless I change the java.ext.dirs setting?
The java.ext.dirs setting automatically adds all jar-files found in the specified directory to the main classloader, which is why the ServiceLoader can find and load TestIface.class (from the Apidocs: "Creates a new service loader for the given service type, using the current thread's context class loader.").
But you should not use java.ext.dirs for this (see here for one of the dangers). And when you use java -jar you cannot use java -cp to set a classpath (you can only use one of them). This leaves you the option to use the URLClassLoader to load additional jars and then call ServiceLoader.load(class from another jar).
Tip: to load other jar-files, use the location of the main.jar file as explained in the answers of this question. Other variables (like startup directory) depend on how and from where Java was started and can easily result in not finding the other jar-files.

Categories