using bytebuddy to intercept class Foo, whihc has two method A,B
in A method, B method get called. if we deleget both A and B to C method in intercetpor class Bar, which call callable#call at first line
what will happen ? what's the execution sequence of those methods ?
package org.wxt.xtools.agents;
import static net.bytebuddy.matcher.ElementMatchers.isAbstract;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
import static net.bytebuddy.matcher.ElementMatchers.not;
import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import net.bytebuddy.utility.JavaModule;
class Foo {
public void methodA() {
System.out.println("method A");
methodB();
}
public void methodB() {
System.out.println("method B");
}
}
class Bar {
#RuntimeType
public static void interceptor(#Origin Class<?> clazz, #Origin Method method, #SuperCall Callable<?> callable,
#net.bytebuddy.implementation.bind.annotation.This Object inst) throws Exception {
callable.call();
System.out.println("intercepting " + method.getName());
}
}
public class Test {
public static void premain(String agentArgs, Instrumentation inst) throws IOException {
AgentBuilder.Transformer methodsTransformer = new AgentBuilder.Transformer() {
#Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
ClassLoader classLoader, JavaModule javaModule) {
return builder.method(namedOneOf("methodA", "methodB").and(not(isAbstract())))
.intercept(MethodDelegation.to(Bar.class));
}
};
AgentBuilder.Listener listener = new AgentBuilder.Listener.WithErrorsOnly(
new AgentBuilder.Listener.StreamWriting(System.out));
new AgentBuilder.Default().type(named("org.wxt.xtools.agents.Foo")).transform(methodsTransformer)
.with(listener).installOn(inst);
}
public static void main(String[] args) throws IOException {
premain(null, ByteBuddyAgent.install());
new Foo().methodA();
}
}
results
method A
method B
intercepting methodB
intercepting methodA
You can of course just try it, but what will happen is that the internal call will again be intercepted. Methods do not know who is calling them. To avoid this, you can discover the caller via a StackWalker or by generating a stack trace using an exception.
Related
I have the following implementation:
public interface BusinessResource {
#RequiresAuthorization
public ResponseEnvelope getResource(ParamObj param);
}
and
#Component
public class BusinessResourceImpl implements BusinessResource {
#Autowired
public Response getResource(ParamObj param) {
return Response.ok().build();
}
}
and
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class AuthorizerAspect {
protected static final Logger LOGGER =
LoggerFactory.getLogger(AuthorizerAspect.class);
#Autowired
public AuthorizerAspect() {
LOGGER.info("Break point works here..." +
"so spring is creating the aspect as a component...");
}
#Around(value="#annotation(annotation)")
public Object intercept(ProceedingJoinPoint jp,
RequiresAuthorization annotation) throws Throwable {
LOGGER.info("BEGIN");
jp.proceed();
LOGGER.info("END");
}
}
The maven dependencies are properly configured with the spring-boot-starter-aop dependency. So what happens is that AuthorizerAspect won't intercept around the getResource method if the #RequiresAuthorization is used on the declared method of the BusinessResource interface, but if I change the implementation to annotate the same method now in the BusinessResourceImpl class, the aspect will take place.
NOTE: With the annotation in the interface level, the proxy isn't even created, whereas the annotation being placed in the implementation level will create a proxy for the resource.
Question is: Is there a way to advice objects which the annotation is present just on the interface?
May this alternative be useful for those who like me found no direct approach to sort that limitation on Spring AOP through proxies:
public interface BusinessResource {
#RequiresAuthorization
public ResponseEnvelope getResource(ParamObj param);
}
And
#Component
public class BusinessResourceImpl implements BusinessResource {
#Autowired
public Response getResource(ParamObj param) {
return Response.ok().build();
}
}
And
import import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
#Configuration
public class AuthorizerAspect {
protected static final Logger LOGGER =
LoggerFactory.getLogger(AuthorizerAspect.class);
#Autowired
public AuthorizerAspect() {
LOGGER.info("Break point works here..." +
"so spring is creating the aspect as a component...");
}
public Object invoke(MethodInvocation invocation) throws Throwable {
LOGGER.info("BEGIN");
invocation.proceed();
LOGGER.info("END");
}
#Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
return new DefaultAdvisorAutoProxyCreator();
}
#Bean("requiresAuthorizationPointcut")
public AbstractPointcutAdvisor createPointcut() {
return new AbstractPointcutAdvisor() {
private static final long serialVersionUID = 4733447191475535406L;
#Override
public Advice getAdvice() {
return AuthorizerAspect.this;
}
#Override
public Pointcut getPointcut() {
return new StaticMethodMatcherPointcut() {
#Override
public boolean matches(Method method, Class<?> targetClass) {
if (method.isAnnotationPresent(RequiresAuthorization.class)) {
return true;
}
if (method.getDeclaringClass().isInterface()) {
String methodName = method.getName();
try {
Method targetMethod = targetClass.getMethod(methodName, method.getParameterTypes());
return targetMethod != null && targetMethod.isAnnotationPresent(RequiresAuthorization.class);
} catch (NoSuchMethodException |
SecurityException e) {
LOGGER.debug("FAILURE LOG HERE",
e.getMessage());
return false;
}
}
return method.isAnnotationPresent(RequiresAuthorization.class);
}
};
}
};
}
}
So as you'll notice, we're sorting it by using method interceptors.
Say I have a method signature that is
public void accept(ParentInterface parent)
where ParentInterface is an interface. I want my pointcut to only specifically target a class TestA, but not a class TestB, both which implement the ParentInterface.
Currently, I have the following pointcut:
#Pointcut("call(public void accept(package.ParentInterface))")
But that would catch instances where accept is taking in a TestB instance too. Is there a method of fixing this?
Interface + implementations + driver application:
package de.scrum_master.app;
public interface ParentInterface {}
package de.scrum_master.app;
public class TestA implements ParentInterface {}
package de.scrum_master.app;
public class TestB implements ParentInterface {}
package de.scrum_master.app;
public class Application {
public void accept(ParentInterface parent) {}
public static void main(String[] args) {
Application application = new Application();
application.accept(new TestA());
application.accept(new TestB());
}
}
Aspect pinning down argument type via args() + pointcut method signature:
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import de.scrum_master.app.TestA;
#Aspect
public class MyAspect {
#Pointcut("call(public void accept(de.scrum_master.app.ParentInterface)) && args(argument)")
static void acceptCalls(TestA argument) {}
#Before("acceptCalls(argument)")
public void intercept(TestA argument, JoinPoint thisJoinPoint) {
System.out.println(thisJoinPoint + " -> " + argument);
}
}
Console log:
call(void de.scrum_master.app.Application.accept(ParentInterface)) -> de.scrum_master.app.TestA#4a574795
can someone help me with using property file for a sample login application? this helps in achieving me for another big automation.
I have given objects in objects.propreties
in main java class how shall i proceed with?
package valuescompare;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class practice {
public static FileInputStream fis;
public static String propertyfilepath="E:\\Ashik\\wkspSelenium\\valuescompare\\src\\valuescompare\\object.properties";
public static String getProperty(String key) throws IOException, FileNotFoundException{
fis=new FileInputStream(propertyfilepath);
Properties prop=new Properties();
prop.load(fis);
return prop.getProperty(key);
}
static WebDriver driver=new FirefoxDriver();
public static void openBrowser() throws FileNotFoundException, IOException {
//public WebDriver driver;
driver.get(getProperty("url"));
//maximizes the window
driver.manage().window().maximize();
Wait(1000);
}
public static void login() throws FileNotFoundException, IOException{
driver.findElement(By.xpath(getProperty("uidxpath"))).sendKeys(getProperty("uid"));
driver.findElement(By.xpath(getProperty("pwdxpath"))).sendKeys(getProperty("pwd"));
driver.findElement(By.xpath(getProperty("submit"))).click();
Wait(5000);
}
public static void main(String[] args) throws FileNotFoundException, IOException {
// TODO Auto-generated method stub
/*practice prac=new practice();
prac.openBrowser();
prac.login(); */
openBrowser();
login();
}
public static void Wait(int time){
try {
Thread.sleep(time);
} catch (Exception e) {
// TODO: handle exception
}
}
}
Say you create a 'config.properties' named file somewhat like this :
userName=admin
password=admin
and say you are using Java as your programming language, then you have to use it in this manner:
Properties properties = new Properties();
properties.load(new FileInputStream("Config.properties"));
String uName = properties.getProperty("userName");
String pwd = properties.getProperty("password");
Now you have got the values fetched from properties file, use it wherever required.
For more info you may refer this link: http://www.mkyong.com/java/java-properties-file-examples/
I am trying to make an automation wizard that would take some files from system (via a command handler) and make its relevant applet.
I shall try to explain my senario.
I made a plugin for new command "newModule" which is handled via "newModuleHandler.java". so newModuleHandler extends AbstractHandler.
Now i would like to make a wizard (applet) that helps me with certain selections that i need to make in order to complete that "newModule" command. so
newModuleHandler extends Applet too.
i wrote newModuleHandler something like this.
package archetypedcomponent.commands;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import java.applet.*;// required when you create an applet
import java.awt.Graphics;
public class newModuleHandler extends AbstractHandler {
#Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return true;
}
#Override
public boolean isHandled() {
// TODO Auto-generated method stub
return true;
}
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
// TODO Auto-generated method stub
return null;
}
public class HelloWorld extends Applet
{
// The method that will be automatically called when the applet is started
public void init()
{
// It is required but does not need anything.
System.out.println("Applet initiated");
}
// This method gets called when the applet is terminated
// That's when the user goes to another page or exits the browser.
public void stop()
{
// no actions needed here now.
System.out.println("Applet Stopped");
}
// The standard method that you have to use to paint things on screen
// This overrides the empty Applet method, you can't called it "display" for example.
public void paint(Graphics g)
{
//method to draw text on screen
// String first, then x and y coordinate.
System.out.println("Applet in paint");
g.drawString("Hey hey hey",20,20);
g.drawString("Hellooow World",20,40);
}
}
}
Now when the command will b given this method will be called
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
// TODO Auto-generated method stub
return null;
}
and applet will have to be called inside it. my question is how to call it?
========================================================================================
i was able to solve my problem but m replying here so that somebody who is also facing same problem can b guided
this is my new "newModuleHandler.java"
package archetypedcomponent.commands;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import java.applet.*;// required when you create an applet
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
public class newModuleHandler extends AbstractHandler {
#Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return true;
}
#Override
public boolean isHandled() {
// TODO Auto-generated method stub
return true;
}
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
// TODO Auto-generated method stub
// call applet here
JFrame jp1 = new JFrame();
Loader a=new Loader ();
jp1.getContentPane().add(a, BorderLayout.CENTER);
jp1.setSize(new Dimension(500,500));
jp1.setVisible(true);
return null;
}
}
i made a new Loader.java which extends applet
package archetypedcomponent.commands;
import java.applet.Applet;
import java.awt.Graphics;
public class Loader extends Applet
{
// The method that will be automatically called when the applet is started
public void init()
{
// It is required but does not need anything.
System.out.println("Applet initiated");
// Graphics g=new ;
}
// This method gets called when the applet is terminated
// That's when the user goes to another page or exits the browser.
public void stop()
{
// no actions needed here now.
System.out.println("Applet Stopped");
}
// The standard method that you have to use to paint things on screen
// This overrides the empty Applet method, you can't called it "display" for example.
public void paint(Graphics g)
{
//method to draw text on screen
// String first, then x and y coordinate.
System.out.println("Applet in paint");
g.drawString("Hey hey hey",20,20);
g.drawString("Hellooow World",20,40);
}
}
Now whatever i need applet to do can b done in paint of Loader.
An applet can have more than one Object, so extends AbstractHandler in some other class that the applet has a reference to.
I've followed a lot of the guides and forum posts online but haven't had any luck getting this to work inside TestNG. It's a selenium grid based test, programmed in eclipse.
Had trouble, so used the libraries listed in the suggestion of this forum post: http://clearspace.openqa.org/message/66867
I am trying to run the suite in the testNG test plugin for eclipse (org.testng.eclipse). Also tried running the jar from command line through selenium grid to no avail.
Since I'm not a java developer, to be honest I'm not entirely sure what to look for. I've some familiarity with Java thanks to the Processing environment, but I've kind of been thrown into java/eclipse for this task and am at a bit of a loss. Anyway, any help is appreciated and thank you in advance.
Here's my code:
suite.java:
package seleniumRC;
//import com.thoughtworks.selenium.*;
//import junit.framework.*;
//import java.util.regex.Pattern;
//import static org.testng.AssertJUnit.assertTrue;
//import org.testng.annotations.AfterMethod;
//import org.testng.annotations.BeforeMethod;
//import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class suite extends Testcase1 {
#Test(groups = {"example", "firefox", "default"}, description = "test1")
public void user1() throws Throwable {
testCase1();
}
#Test(groups = {"example", "firefox", "default"}, description = "test2")
public void user2() throws Throwable {
testCase1();
}
}
The actual test case
package seleniumRC;
//import com.thoughtworks.selenium.*;
//import org.testng.annotations.*;
//import static org.testng.Assert.*;
//import com.thoughtworks.selenium.grid.demo.*;
//import junit.framework.*;
//import com.ibm.icu.*;
//import java.util.regex.Pattern;
//import static org.testng.AssertJUnit.assertTrue;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
public class Testcase1 extends SeleneseTestNgHelper {
private static int $itter = 10;
public static void main(String args[]) {
//junit.textui.TestRunner.run(Suite());
}
//public static Test Suite() {
// return new TestSuite(Testcase1.class);
//}
// public void setUp() throws Exception {
// setUp("http://localhost:8080/test", "*firefox");
//}
#BeforeMethod(groups = {"default", "example"}, alwaysRun = true)
#Parameters({"seleniumHost", "seleniumPort", "browser", "webSite"})
protected void startSession(String seleniumHost, int seleniumPort, String browser, String webSite) throws Exception {
startSession(seleniumHost, seleniumPort, browser, webSite);
selenium.setTimeout("120000");
}
#AfterMethod(groups = {"default", "example"}, alwaysRun = true)
protected void closeSession() throws Exception {
closeSession();
}
public void testCase1() throws Exception {
selenium.open("/login.action#login");
selenium.type("userName", "foo");
selenium.type("password", "bar");
selenium.click("login");
selenium.waitForPageToLoad("30000");
selenium.click("link=test");
Thread.sleep(4000);
selenium.click("//tr[4]/td[1]/a");
if(selenium.isElementPresent("//input[#id='nextButton']") != false){
selenium.click("//div[2]/input");
}
Thread.sleep(2000);
for(int i=0; i < $itter; i++) {
if(selenium.isElementPresent("//label") != false){
selenium.click("//label");
selenium.click("submitButton");
Thread.sleep(1500);
}
else{ Thread.sleep(1500);}
}
selenium.click("//body/div[2]/div[1]/div/a");
Thread.sleep(1500);
selenium.click("//a[contains(text(),'Finish Now')]");
Thread.sleep(2000);
selenium.click("link=View Results");
Thread.sleep(30000);
selenium.click("showAllImgCaption");
Thread.sleep(12000);
selenium.click("generateTimeButton");
Thread.sleep(2000);
selenium.click("link=Logout");
selenium.waitForPageToLoad("15000");
}
}
and the SeleneseTestNGHelper class
package seleniumRC;
import java.lang.reflect.Method;
//import java.net.BindException;
import com.thoughtworks.selenium.*;
//import org.openqa.selenium.SeleniumTestEnvironment;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverBackedSelenium;
//import org.openqa.selenium.environment.GlobalTestEnvironment;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
public class SeleneseTestNgHelper extends SeleneseTestCase
{
private static Selenium staticSelenium;
#BeforeTest
#Override
#Parameters({"selenium.url", "selenium.browser"})
public void setUp(#Optional String url, #Optional String browserString) throws Exception {
if (browserString == null) browserString = runtimeBrowserString();
WebDriver driver = null;
if (browserString.contains("firefox") || browserString.contains("chrome")) {
System.setProperty("webdriver.firefox.development", "true");
driver = new FirefoxDriver();
} else if (browserString.contains("ie") || browserString.contains("hta")) {
driver = new InternetExplorerDriver();
} else {
fail("Cannot determine which browser to load: " + browserString);
}
if (url == null)
url = "http://localhost:4444/selenium-server";
selenium = new WebDriverBackedSelenium(driver, url);
staticSelenium = selenium;
}
#BeforeClass
#Parameters({"selenium.restartSession"})
public void getSelenium(#Optional("false") boolean restartSession) {
selenium = staticSelenium;
if (restartSession) {
selenium.stop();
selenium.start();
}
}
#BeforeMethod
public void setTestContext(Method method) {
selenium.setContext(method.getDeclaringClass().getSimpleName() + "." + method.getName());
}
#AfterMethod
#Override
public void checkForVerificationErrors() {
super.checkForVerificationErrors();
}
#AfterMethod(alwaysRun=true)
public void selectDefaultWindow() {
if (selenium != null) selenium.selectWindow("null");
}
#AfterTest(alwaysRun=true)
#Override
public void tearDown() throws Exception {
// super.tearDown();
}
//#Override static method of super class (which assumes JUnit conventions)
public static void assertEquals(Object actual, Object expected) {
SeleneseTestBase.assertEquals(expected, actual);
}
//#Override static method of super class (which assumes JUnit conventions)
public static void assertEquals(String actual, String expected) {
SeleneseTestBase.assertEquals(expected, actual);
}
//#Override static method of super class (which assumes JUnit conventions)
public static void assertEquals(String actual, String[] expected) {
SeleneseTestBase.assertEquals(expected, actual);
}
//#Override static method of super class (which assumes JUnit conventions)
public static void assertEquals(String[] actual, String[] expected) {
SeleneseTestBase.assertEquals(expected, actual);
}
//#Override static method of super class (which assumes JUnit conventions)
public static boolean seleniumEquals(Object actual, Object expected) {
return SeleneseTestBase.seleniumEquals(expected, actual);
}
//#Override static method of super class (which assumes JUnit conventions)
public static boolean seleniumEquals(String actual, String expected) {
return SeleneseTestBase.seleniumEquals(expected, actual);
}
#Override
public void verifyEquals(Object actual, Object expected) {
super.verifyEquals(expected, actual);
}
#Override
public void verifyEquals(String[] actual, String[] expected) {
super.verifyEquals(expected, actual);
}
}
So I solved this by dropping the seleniumTestNGHelper class and reworking the classpaths by way of the ant file. It required completely working my suite/original testcases, but worked well within Grid.