aspectj - AND and OR in the same pointcut - aop

I'd like to do something when getAll(...) or getRec(...) methods are called in com.acme.dao.impl.*DaoImpl classes but exclude the com.acme.dao.impl.*ViewDaoImpl classes.
I can do the 1st requirement with
execution(* com.acme.dao.impl.*DaoImpl.getAll(..)) || execution(* com.acme.dao.impl.*DaoImpl.getNRecs(..))
but not sure how to exclude the *ViewDaoImpl classes.
I presume I should do something like
!execution(* com.acme.dao.impl.*ViewDaoImpl.*(..))
but how to add to the include expression?
Thanks,
V.

You have several options. The one closest to what you already have is:
(execution(* com.acme.dao.impl.*DaoImpl.getAll(..)) || execution(* com.acme.dao.impl.*DaoImpl.getNRecs(..))) &&
!execution(* com.acme.dao.impl.*ViewDaoImpl.*(..))
But you can also use this, I think it is a bit more readable:
within(com.acme.dao.impl.*DaoImpl) && !within(*..*ViewDaoImpl) &&
(execution(* getAll(..)) || execution(* getNRecs(..)))
Assuming that all DAO classes would implement the same interface as given above, this would also work (Dao+ captures all implementing classes and their subclasses):
within(com.acme.dao.impl.Dao+) && !within(*..*ViewDaoImpl) &&
(execution(* getAll(..)) || execution(* getNRecs(..)))
Here is a pure AspectJ example, but it should be just the same aspect code for Spring AOP:
Sample application classes:
package com.acme.dao.impl;
import java.util.List;
public interface Dao {
List getAll();
List getNRecs();
void doSomething();
}
package com.acme.dao.impl;
import java.util.ArrayList;
import java.util.List;
public class FirstDaoImpl implements Dao {
#Override
public List getAll() {
return new ArrayList();
}
#Override
public List getNRecs() {
return new ArrayList();
}
#Override
public void doSomething() {}
}
package com.acme.dao.impl;
import java.util.ArrayList;
import java.util.List;
public class SecondDaoImpl implements Dao {
#Override
public List getAll() {
return new ArrayList();
}
#Override
public List getNRecs() {
return new ArrayList();
}
#Override
public void doSomething() {}
}
package com.acme.dao.impl;
import java.util.ArrayList;
import java.util.List;
public class MyViewDaoImpl implements Dao {
#Override
public List getAll() {
return new ArrayList();
}
#Override
public List getNRecs() {
return new ArrayList();
}
#Override
public void doSomething() {}
}
Driver application:
package de.scrum_master.app;
import java.util.Arrays;
import com.acme.dao.impl.Dao;
import com.acme.dao.impl.FirstDaoImpl;
import com.acme.dao.impl.MyViewDaoImpl;
import com.acme.dao.impl.SecondDaoImpl;
public class Application {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
for (Class<?> clazz : Arrays.asList(FirstDaoImpl.class, SecondDaoImpl.class, MyViewDaoImpl.class)) {
Dao dao = (Dao) clazz.newInstance();
dao.getAll();
dao.getNRecs();
dao.doSomething();
}
}
}
Aspect:
I have added a lot of line breaks and indentation within the pointcut strings, of course you don't need to do that. It is just for clarity here in this Q/A scenario on StackOverflow.
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class DaoAspect {
#Before(
"(" +
"execution(* com.acme.dao.impl.*DaoImpl.getAll(..)) || " +
"execution(* com.acme.dao.impl.*DaoImpl.getNRecs(..))" +
") && " +
"!execution(* com.acme.dao.impl.*ViewDaoImpl.*(..))"
)
public void firstVariant(JoinPoint thisJoinPoint) {
System.out.println("[1] " + thisJoinPoint);
}
#Before(
"within(com.acme.dao.impl.*DaoImpl) && " +
"!within(*..*ViewDaoImpl) && " +
"(" +
"execution(* getAll(..)) || " +
"execution(* getNRecs(..))" +
")"
)
public void secondVariant(JoinPoint thisJoinPoint) {
System.out.println("[2] " + thisJoinPoint);
}
#Before(
"within(com.acme.dao.impl.Dao+) && " +
"!within(*..*ViewDaoImpl) && " +
"(" +
"execution(* getAll(..)) || " +
"execution(* getNRecs(..))" +
")"
)
public void thirdVariant(JoinPoint thisJoinPoint) {
System.out.println("[3] " + thisJoinPoint);
}
}
Console log:
[1] execution(List com.acme.dao.impl.FirstDaoImpl.getAll())
[2] execution(List com.acme.dao.impl.FirstDaoImpl.getAll())
[3] execution(List com.acme.dao.impl.FirstDaoImpl.getAll())
[1] execution(List com.acme.dao.impl.FirstDaoImpl.getNRecs())
[2] execution(List com.acme.dao.impl.FirstDaoImpl.getNRecs())
[3] execution(List com.acme.dao.impl.FirstDaoImpl.getNRecs())
[1] execution(List com.acme.dao.impl.SecondDaoImpl.getAll())
[2] execution(List com.acme.dao.impl.SecondDaoImpl.getAll())
[3] execution(List com.acme.dao.impl.SecondDaoImpl.getAll())
[1] execution(List com.acme.dao.impl.SecondDaoImpl.getNRecs())
[2] execution(List com.acme.dao.impl.SecondDaoImpl.getNRecs())
[3] execution(List com.acme.dao.impl.SecondDaoImpl.getNRecs())
As you can see, all three variants do exactly the same. Choose according to your own preference.

Related

Jackson-Serialiser: Ignore Field at Serialisation Time

My situation asks for a bit more complex serialisation. I have a class Available (this is a very simplified snippet):
public class Available<T> {
private T value;
private boolean available;
...
}
So a POJO
class Tmp {
private Available<Integer> myInt = Available.of(123);
private Available<Integer> otherInt = Available.clean();
...
}
would normally result in
{"myInt":{available:true,value:123},"otherInt":{available:false,value:null}}
However, I want a serialiser to render the same POJO like this:
{"myInt":123}
What I have now:
public class AvailableSerializer extends JsonSerializer<Available<?>> {
#Override
public void serialize(Available<?> available, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException, JsonProcessingException {
if (available != null && available.isAvailable()) {
jsonGenerator.writeObject(available.getValue());
}
// MISSING: nothing at all should be rendered here for the field
}
#Override
public Class<Available<?>> handledType() {
#SuppressWarnings({ "unchecked", "rawtypes" })
Class<Available<?>> clazz = (Class) Available.class;
return clazz;
}
}
A test
#Test
public void testSerialize() throws Exception {
SimpleModule module = new SimpleModule().addSerializer(new AvailableSerializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
System.out.println(objectMapper.writeValueAsString(new Tmp()));
}
outputs
{"myInt":123,"otherInt"}
Can anyone tell me how to do the "MISSING"-stuff? Or if I'm doing it all wrong, how do I do it then?
The restriction I have is that I don't want the developers to add #Json...-annotations all the time to fields of type Available. So the Tmp-class above is an example of what a typical using class should look like. If that's possible...
Include.NON_DEFAULT
If we assume that your clean method is implemented in this way:
class Available<T> {
public static final Available<Object> EMPTY = clean();
//....
#SuppressWarnings("unchecked")
static <T> Available<T> clean() {
return (Available<T>) EMPTY;
}
}
You can set serialisation inclusion to JsonInclude.Include.NON_DEFAULT value and it should skip values set to EMPTY (default) values. See below example:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import java.io.IOException;
public class JsonApp {
public static void main(String[] args) throws Exception {
SimpleModule module = new SimpleModule();
module.addSerializer(new AvailableSerializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
System.out.println(objectMapper.writeValueAsString(new Tmp()));
}
}
class AvailableSerializer extends JsonSerializer<Available<?>> {
#Override
public void serialize(Available<?> value, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException {
jsonGenerator.writeObject(value.getValue());
}
#Override
#SuppressWarnings({"unchecked", "rawtypes"})
public Class<Available<?>> handledType() {
return (Class) Available.class;
}
}
Above code prints:
{"myInt":123}
Custom BeanPropertyWriter
If you do not want to use Include.NON_DEFAULT you can write your custom BeanPropertyWriter and skip all values you want. See below example:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
SimpleModule module = new SimpleModule();
module.addSerializer(new AvailableSerializer());
module.setSerializerModifier(new BeanSerializerModifier() {
#Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
List<BeanPropertyWriter> writers = new ArrayList<>(beanProperties.size());
for (BeanPropertyWriter writer : beanProperties) {
if (writer.getType().getRawClass() == Available.class) {
writer = new SkipNotAvailableBeanPropertyWriter(writer);
}
writers.add(writer);
}
return writers;
}
});
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
System.out.println(objectMapper.writeValueAsString(new Tmp()));
}
}
class AvailableSerializer extends JsonSerializer<Available<?>> {
#Override
public void serialize(Available<?> value, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException {
jsonGenerator.writeObject(value.getValue());
}
#Override
#SuppressWarnings({"unchecked", "rawtypes"})
public Class<Available<?>> handledType() {
return (Class) Available.class;
}
}
class SkipNotAvailableBeanPropertyWriter extends BeanPropertyWriter {
SkipNotAvailableBeanPropertyWriter(BeanPropertyWriter base) {
super(base);
}
#Override
public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception {
// copier from super.serializeAsField(bean, gen, prov);
final Object value = (_accessorMethod == null) ? _field.get(bean) : _accessorMethod.invoke(bean, (Object[]) null);
if (value == null || value instanceof Available && !((Available) value).isAvailable()) {
return;
}
super.serializeAsField(bean, gen, prov);
}
}
Above code prints:
{"myInt":123}
After Michał Ziober's answer I had to look for something regarding Include.NON_DEFAULT and the default object and ran into this answer explaining Include.NON_EMPTY that Google didn't return in my first research (thanks Google).
So things become easier, it's now:
public class AvailableSerializer extends JsonSerializer<Available<?>> {
#Override
public void serialize(Available<?> available, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException, JsonProcessingException {
jsonGenerator.writeObject(available.getValue());
}
#Override
public Class<Available<?>> handledType() {
#SuppressWarnings({ "unchecked", "rawtypes" })
Class<Available<?>> clazz = (Class) Available.class;
return clazz;
}
#Override
public boolean isEmpty(SerializerProvider provider, Available<?> value) {
return value == null || !value.isAvailable();
}
}
with the test
#Test
public void testSerialize() throws Exception {
SimpleModule module = new SimpleModule().addSerializer(availableSerializer);
objectMapper.registerModule(module);
objectMapper.configOverride(Available.class).setInclude(
// the call comes from JavaDoc of objectMapper.setSerializationInclusion(...)
JsonInclude.Value.construct(JsonInclude.Include.NON_EMPTY, JsonInclude.Include.ALWAYS));
Tmp tmp = new Tmp();
assertThat(objectMapper.writeValueAsString(tmp)).isEqualTo("{\"myInt\":123}");
tmp.otherInt.setValue(123);
assertThat(objectMapper.writeValueAsString(tmp)).isEqualTo("{\"myInt\":123,\"otherInt\":123}");
}
So please, if you upvote my answer please also upvote Michał Ziober's as that's also working with a mildly different approach.

spring-boot-starter-aop around annotated interface's method won't advice my aspect

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.

#EventHandler events not working

I am trying to make a simple addition to my plugin so that when someone joins they receive a message that says "Heyyyyyyy". My plugin has a few commands also.
Here's my Main class:
package me.ben.test;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin implements Listener {
#Override
public void onEnable() {
this.getServer().getPluginManager().registerEvents(new Click(), this);
getLogger().info("The Plugin Has Been Enabled!");
}
#Override
public void onDisable() {
getLogger().info("The Plugin Has Been Disabled!");
}
public boolean onCommand(CommandSender sender, Command cmd, String label,
String[] args) {
if (cmd.getName().equalsIgnoreCase("hello") && sender instanceof Player) {
Player player = (Player) sender;
player.sendMessage("Hello, " + player.getName() + "!");
return true;
} else if (cmd.getName().equalsIgnoreCase("isonline")
&& args.length == 1) {
Player target = Bukkit.getServer().getPlayer(args[0]);
if (target == null) {
sender.sendMessage(ChatColor.AQUA + "Player " + args[0]
+ " is not online.");
return true;
} else if (target != null) {
sender.sendMessage(ChatColor.AQUA + "Player " + args[0]
+ " is online.");
return true;
} else {
return false;
}
}
return false;
}
}
and here is my Click class:
package me.ben.test;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;
public class Click extends JavaPlugin implements Listener {
#EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.getPlayer().sendMessage("Heyyyyyyy");
}
}
All of the #EventHandler things are not working so I quick made this simple one.
You can have only one class that extends JavaPlugin. Remove extends JavaPlugin from your Click Class - only your main class should extend JavaPlugin.
Check out Bukkit's official plugin tutorial for help on coding Bukkit Plugins.
You are using Listener in your Main class but you are not handling any event there, use it only when you want the class to be able to handler bukkit events.
You can use Listener with your Main class if you want, but you'll need to put the methods that handles events in your main class, but it'll become messy in big projects...
You also don't need to extend JavaPlugin everywhere, just in your main class.
If you want to use your main class:
public class Main extends JavaPlugin implements Listener {
#Override
public void onEnable() {
this.getServer().getPluginManager().registerEvents(this, this);
getLogger().info("The Plugin Has Been Enabled!");
}
#EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.getPlayer().sendMessage("Heyyyyyyy");
}
}
If you want to use a separated class to handle events:
public class Main extends JavaPlugin {
#Override
public void onEnable() {
this.getServer().getPluginManager().registerEvents(new Click(), this);
getLogger().info("The Plugin Has Been Enabled!");
}
}
public class Click implements Listener {
#EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.getPlayer().sendMessage("Heyyyyyyy");
}
}
Don't forget that you need to create a plugin.yml file correctly otherwise nothing will work.

How do I override Class<?>.getName() for certain classes?

My goal is to be able to override what I get back from CustomClass.class.getName() and CustomClass.getClass().getName()
It should return a custom value, which I think is best to define in an attribute like
#NameOverride("Custom.fully.qualified.class.name")
public class CustomClass {}
Is there any way to do that?
Fred's answer is okay, but his aspect could be somewhat more elegant with less code and especially fewer reflection calls. Sorry, I prefer AspectJ native code style, but #AspectJ annotation style would not be much longer:
String around(Class clazz) : call(public String Class.getName()) && target(clazz) {
NameOverride nameOverride = (NameOverride) clazz.getAnnotation(NameOverride.class);
return nameOverride == null ? proceed(clazz) : nameOverride.value();
}
Here is the full source code. I added a class without annotation to show the different behaviour and also a restriction to class definitions - #Target(ElementType.TYPE) - to the annotation class. I am also showing package names and imports:
package test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface NameOverride {
String value();
}
package test;
public class NormalClass {}
package test;
#NameOverride("Custom.fully.qualified.class.name")
public class CustomClass {}
package test;
public class Main {
public static void main(String[] args) {
System.out.println(NormalClass.class.getName());
System.out.println(CustomClass.class.getName());
System.out.println(new NormalClass().getClass().getName());
System.out.println(new CustomClass().getClass().getName());
}
}
package aspectj;
import test.NameOverride;
public aspect GetNameOverrider {
#SuppressWarnings({ "unchecked", "rawtypes" })
String around(Class clazz) : call(public String Class.getName()) && target(clazz) {
NameOverride nameOverride = (NameOverride) clazz.getAnnotation(NameOverride.class);
return nameOverride == null ? proceed(clazz) : nameOverride.value();
}
}
The output:
test.NormalClass
Custom.fully.qualified.class.name
test.NormalClass
Custom.fully.qualified.class.name
This is for sure not the best/fastest solution but maybe a POC...
First of all the file structure:
./src/aspectj:
GetNameOverrider.aj
./src/test:
CustomClass.java Main.java NameOverride.java
NameOverride.java:
#Retention(RetentionPolicy.RUNTIME)
public #interface NameOverride {
String value();
}
GetNameOverrider.aj:
#Aspect
public class GetNameOverrider {
#Around("call(String getName()) && !within(aspectj..*)")
public String advice(ProceedingJoinPoint pjp) throws Throwable {
String ret = (String) pjp.proceed();
String className = "" + pjp.getTarget();
className = className.replace("class ", "");
try {
test.NameOverride anno = Class.forName(className).getAnnotation(
test.NameOverride.class);
if (anno != null) {
return anno.value();
}
} catch (ClassNotFoundException e) {
return ret;
}
return ret;
}
}
gives me for Main.java:
public class Main {
public static void main(String[] args) {
System.out.println(CustomClass.class.getName());
System.out.println(new CustomClass().getClass().getName());
}
}
the output:
Custom.fully.qualified.class.name
Custom.fully.qualified.class.name

TestNG + Selenium woes. noClassDef error, TestNG based selenium test

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.