annotation to generate source code for same file in java - java

I am trying to define a simple annotation and use it during compile time only to add a simple method to the consumed source file/class file but nothing is getting added.
I am using maven and java 1.8.
Below is the code and not sure where it is going wrong
Annotation class definition:
package com.test.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.SOURCE)
public #interface AddMethod {
}
Processor for the annotation
package com.test.annotations;
import com.google.auto.service.AutoService;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import java.util.stream.Collectors;
#SupportedAnnotationTypes("com.test.annotations.AddMethod")
#SupportedSourceVersion(SourceVersion.RELEASE_8)
#AutoService(Processor.class)
public class AddMethodProcessor extends AbstractProcessor {
#Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
// get all the classes annotated with ToJsonString class
Collection<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(AddMethod.class);
annotatedElements.forEach(e -> {
// some code to get the class name
try {
writeBuilderFile(qualifiedClassName);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
});
return true;
}
private void writeBuilderFile(String qualifiedClassName) throws IOException {
String packageName = null;
int lastDot = qualifiedClassName.lastIndexOf('.');
if (lastDot > 0) {
packageName = qualifiedClassName.substring(0, lastDot);
}
String simpleClassName = qualifiedClassName.substring(lastDot + 1);
JavaFileObject generatedSourceFile = processingEnv.getFiler()
.createSourceFile(qualifiedClassName);
try (PrintWriter out = new PrintWriter(generatedSourceFile.openWriter())) {
if (packageName != null) {
out.print("package ");
out.print(packageName);
out.println(";");
out.println();
}
out.print("public class ");
out.print(simpleClassName);
out.println(" {");
out.println();
out.print(" public ");
out.print("String");
out.println(" testMethod() {");
out.println(" return \"this is a test method\" ");
out.println(" }");
out.println();
out.println("}");
}
}
}
After this, I am running mvn install to install the jar in my .m2 repository so that the consumer can use it.
consumer project:
pom.xml
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>add-method</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
<generatedSourcesDirectory>${project.build.directory}
/generated-sources/</generatedSourcesDirectory>
<annotationProcessors>
<annotationProcessor>
com.test.annotations.AddMethodProcessor
</annotationProcessor>
</annotationProcessors>
</configuration>
</plugin>
</plugins>
</build>
</project>
Test class using the annotation
package org.example;
import com.test.annotations.AddMethod;
#AddMethod
public class Test {
private String x;
}
On running build in intellij, I could not see the source file or class file having the auto generated method.

Related

Problem migrating from AspectJ to Byte Buddy Plugin

I am attempting to migrate an AspectJ project to a Byte Buddy plugin and having some difficulty. I want to do compile-time byte code modifications.
The exception I am getting is :
[ERROR] Failed to execute goal net.bytebuddy:byte-buddy-maven-plugin:1.11.0:transform (default) on project timing-example: Failed to transform class files in /tmp/timing-example/target/classes: protected void com.walterjwhite.examples.timing.TimingExampleCommandLineHandler.doRun(java.lang.String[]) does not define an index 1 -> [Help 1]
Plugin:
NOTE:
package com.walterjwhite.timing.plugin;
import static net.bytebuddy.matcher.ElementMatchers.*;
import com.walterjwhite.timing.annotation.Timing;
import java.io.IOException;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.build.Plugin;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.matcher.ElementMatchers;
#HashCodeAndEqualsPlugin.Enhance
public class TimingPlugin extends Plugin.ForElementMatcher implements Plugin.Factory {
public TimeoutPlugin() {
super(declaresMethod(isAnnotatedWith(Timing.class)));
}
#Override
public DynamicType.Builder<?> apply(
DynamicType.Builder<?> builder,
TypeDescription typeDescription,
ClassFileLocator classFileLocator) {
System.out.println("Timing: start");
for (MethodDescription.InDefinedShape methodDescription :
typeDescription
.getDeclaredMethods()
.filter(
not(isBridge()).<MethodDescription>and(isAnnotatedWith(Timing.class)))) {
System.out.println("Timing: " + methodDescription);
if (methodDescription.isAbstract()) {
throw new IllegalStateException(
"Cannot implement timing on an abstract method: " + methodDescription);
}
builder = builder.visit(Advice.to(TimingAdvice.class).on(is(methodDescription)));
}
System.out.println("Timing: end");
return builder;
}
Advice:
NOTE: I would like to wrap the original method invocation in a try-catch-finally so I can time it. I'm not sure I can do that with advice. In any case, that is further down the road, I want to see that I can write a plugin and have my code instrumented.
package com.walterjwhite.timing.plugin;
import java.lang.reflect.Method;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
public class TimingAdvice {
#RuntimeType
#Advice.OnMethodEnter
public static void onEnter(#Advice.This Object intercepted, #Origin Method method, #RuntimeType #AllArguments Object[] arguments)
throws Throwable {
System.out.println(System.currentTimeNanos());
}
}
Method being advised:
#Timing
#Override
protected void doRun(String... arguments) {
int i = 0;
while (true) {
try {
System.out.println("i:" + i++);
Thread.sleep(50);
} catch (InterruptedException e) {
System.out.println("Exiting as instructed to do so.");
System.exit(1);
}
}
}
excerpt from pom.xml:
<plugin>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-maven-plugin</artifactId>
<version>1.11.0</version>
<executions>
<execution>
<goals>
<goal>transform</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.walterjwhite.aspects.timing</groupId>
<artifactId>plugin</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
</plugin>
Lastly, the plugin project has the file in place because the byte buddy plugin does pick it up. But, whenever it attempts to transform the class files, it fails. So, my configuration isn't quite right.
EDIT #2:
The pom is partially correct, the other issue I ran into was:
NoClassDefFoundError
This was due to the fact that I needed the dependency also listed as a dependency for the project and not just the plugin. Ie:
<plugin>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-maven-plugin</artifactId>
<version>1.11.0</version>
<executions>
<execution>
<goals>
<goal>transform</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.walterjwhite.aspects.timing</groupId>
<artifactId>plugin</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
</plugin>
</plugins
</build>
<dependencies>
<dependency>
<groupId>com.walterjwhite.aspects.timing</groupId>
<artifactId>plugin</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
...
You are blending annotations from the MethodDelegation API with the Advice API. The annotations are very similar as they intend to support the same approach but an unfortunate side effect is that they get confused. Instead of importing
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
you need to use annotations declared within the Advice class with the same name. Ideally, you prefix all annotations with Advice:
#Advice.OnMethodEnter
public static void onEnter(#Advice.This Object intercepted, #Advice.Origin Method method, #Advice.AllArguments Object[] arguments)
throws Throwable {
System.out.println(System.currentTimeNanos());
}
Note that the #RuntimeType has no equivalent in the Advice API. It is not normally needed.

maven test fails with nullpointer but junit 5 ok

I'm having a strange problem with maven test with Junit 5.
I'd created the test suites with junit tools for each method, every test starts like this.
private Class2Test createTestSubject() {
return new Class2Test();
}
public void test1() throws Exception {
Class2Test testSubject;
String result;
// default test
testSubject = createTestSubject();
result = testSubject.getData();
//testing, assert
}
The line
result = testSubject.getData();
returns a NullPointerException
When I execute the same test via eclipse finish ok. The surefire plugin are defined
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.0</version>
</dependency>
</dependencies>
<configuration>
<systemPropertyVariables>
<entorno>${project.basedir}\resources\maqueta.properties</entorno>
<hibernate>${project.basedir}\resources\hibernate.cfg.xml</hibernate>
</systemPropertyVariables>
<parallel>classes</parallel>
<threadCount>10</threadCount>
</configuration>
</plugin>
I'd tried to change the declaration of the object to dogde the nullpointer but it fails.
Class2Test() is the default constructor, doesn't requiere parameters or read files.
package test.com.my.myself;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import javax.annotation.Generated;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.junit.tools.configuration.base.MethodRef;
import com.my.myself.Class2Test;
import com.google.gson.Gson;
import junitparams.JUnitParamsRunner;
#Generated(value = "org.junit-tools-1.1.0")
#RunWith(JUnitParamsRunner.class)
public class Tester1{
private Class2Test createTestSubject() {
return new Class2Test();
}
#DisplayName("TEST1")
#MethodRef(name = "test1", signature = "()QString;")
#Test
public void test1() throws Exception {
Class2Test testSubject;
String result;
// default test
testSubject = createTestSubject();
result = testSubject.test1();
}
}
and the class to test
public class Class2Test{
private Connection conn = new Connector();
private static final Logger logger = Logger.getLogger(Class2Test.class);
public String test1() {
PrepareStatement pstm = conn.prepareStatement("select 1 from dual");
ResultSet rs = pstm.executeQuery();
...
return 1;
}
}
There was a problem with pom.xml the resources folder was wrong setted. :(

I doing an assigment which require me to create a telegram bot bot

package org.example;
import org.telegram.telegrambots.meta.TelegramBotsApi;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
public class App {
public static void main( String[] args ) {
try {
TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSession.class);
botsApi.registerBot(new s261251Bot());
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
}
package org.example;
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
public class s261251Bot extends TelegramLongPollingBot {
#Override
public String getBotUsername() {
return "username";
}
#Override
public String getBotToken() {
return "..............";
}
#Override
public void onUpdateReceived(Update update) {
SendMessage message = new SendMessage();
message.setChatId(String.valueOf((update.getMessage().getChatId())));
message.setText("hello " + update.getMessage().getFrom().getFirstName() +" " + "\nInsert your matric number." + update.getMessage().getText());
try {
execute(message);
}catch (TelegramApiException e){
e.printStackTrace();
}
}
}
I put the right username and token but in here I replace it with other
I keep getting this error:
C:\Users\safwa\Documents\IntelliJ\assignment-2-safwan0908\src\main\java\my\assignment2\src\main\java\org\example\s261251Bot.java:9:8
java: cannot access java.util.concurrent.CompletableFuture class
file for java.util.concurrent.CompletableFuture not found
I had the same problem.
Make sure you use the correct or the same java version in your project and frameworks.
For more details read this article
In my case, I updated my maven version, using these properties (as described in the article):
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
or
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>LATEST</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>

Apache Camel Context start failure

I am pretty new to Spring Boot, Apache Camel and the ActiveMQ broker. I am trying to create an application which will send a message to a queue which I am hosting locally using Camel for routing.
POM:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>2.22.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-activemq</artifactId>
<version>3.2.0</version>
</dependency>
MsgRouteBuilder:
public void configure() throws Exception {
from("direct:firstRoute")
.setBody(constant("Hello"))
.to("activemq:queue:myQueue");
}
application.yaml:
activemq:
broker-url: tcp://localhost:61616
user: meAd
password: meAd
MainApp.java:
package me.ad.myCamel;
import org.apache.camel.CamelContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import me.ad.myCamel.router.MessageRouteBuilder;
#SpringBootApplication
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
#EnableAspectJAutoProxy(proxyTargetClass = true)
#EnableCaching
public class MeAdApp implements CommandLineRunner {
private static final Logger LOG = LoggerFactory.getLogger(MeAdApp.class);
public static void main(String[] args) {
try {
SpringApplication.run(MeAdApp.class, args);
} catch (Exception ex) {
LOG.error(ex.getMessage(), ex);
}
}
#Override
public void run(String... args) throws Exception {
LOG.info("Starting MeAdApp...");
}
}
MyController.java :
#GetMapping(value = "/routing")
public boolean sendToMyQueue() {
sendMyInfo.startRouting();
return true;
}
SendMyInfo.java :
MsgRouteBuilder routeBuilder = new MsgRouteBuilder();
CamelContext ctx = new DefaultCamelContext();
public void startRouting(){
try {
ctx.addRoutes(routeBuilder);
ctx.start();
Thread.sleep(5 * 60 * 1000);
ctx.stop();
}
catch (Exception e) {
e.printStackTrace();
}
}
So, whenever I call my rest end point: /routing, I get the error:
java.lang.NoSuchMethodError: org.apache.camel.RuntimeCamelException.wrapRuntimeException(Ljava/lang/Throwable;)Ljava/lang/RuntimeException;`
Can anybody please point me to the right direction as to why I am getting this error? Any help is greatly appreciated .
You need to have the components of the same version. If you are using camel-core with 3.2.0, use camel-activemq 3.2.0. And, since you are using spring-boot, you can make use of the starter dependencies. Just add these and you are good to go.
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-activemq-starter</artifactId>
<version>3.2.0</version>
</dependency>

How would this testcase ( written in Java using Selenium WebDriver ) look like if the Conductor framework was used?

The following MWE ( described in "Selenium Testing Tools Cookbook, 2nd ed." by Unmesh Gundecha published by Packt publishers ) is a website test using the Selenium Test Framework.
package locators;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.WebElement;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class TableExample {
protected WebDriver driver;
#Before
public void setUp() {
driver = new ChromeDriver();
driver.get("http://dl.dropbox.com/u/55228056/Locators.html");
}
#Test
public void testWebTable() {
WebElement simpleTable = driver.findElement(By.id("items"));
//Get all rows
List<WebElement> rows = simpleTable.findElements(By.tagName("tr"));
assertEquals(3, rows.size());
//Print data from each row
for (WebElement row : rows) {
List<WebElement> cols = row.findElements(By.tagName("td"));
for (WebElement col : cols) {
System.out.print(col.getText() + "\t");
}
System.out.println();
}
}
#After
public void tearDown() {
driver.close();
}
}
Use the following Maven pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>getting-started-with-selenium</groupId>
<artifactId>getting-started-with-selenium</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>getting-started-with-selenium</name>
<description>A quick and easy start-up browser automation framework using Selenium</description>
<properties>
<selenium_version>2.43.1</selenium_version>
</properties>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/main/java</testSourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.ddavison</groupId>
<artifactId>conductor</artifactId>
<version>[1,)</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
</project>
Conductor Framework is a framework built on Selenium which promises to minimize Selenium coding in Java.
AFAIK there is no documentation for Conductor except the page at at https://github.com/conductor-framework/conductor.
How would the testWebTable in the TableExample class ( see test above ) look like if the Conductor framework was used? - Is there more documentation on Conductor, in whatever form?
Through trial and error I found that using the Conductor framework the following class works as expected.
import io.ddavison.conductor.Browser;
import io.ddavison.conductor.Config;
import io.ddavison.conductor.Locomotive;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import java.util.List;
import static org.junit.Assert.assertEquals;
// nilostep
#Config(
url = "http://dl.dropbox.com/u/55228056/Locators.html", // base url that the test launches against
browser = Browser.CHROME, // the browser to use.
hub = "" // you can specify a hub hostname / ip here.
)
public class TableExample2 extends Locomotive {
#Test
public void testWebTable2() {
WebElement simpleTable = waitForElement(By.id("items"));
//Get all rows
List<WebElement> rows = simpleTable.findElements(By.tagName("tr"));
assertEquals(3, rows.size());
//Print data from each row
for (WebElement row : rows) {
List<WebElement> cols = row.findElements(By.tagName("td"));
for (WebElement col : cols) {
System.out.print(col.getText() + "\t");
}
System.out.println();
}
}
}

Categories

Resources