Doing Cyclic Types in ByteBuddy - byte-buddy

I am trying to dynamically create cyclic classes like this with byte-buddy:
class A{
B b;
}
class B{
A a;
}
I have looked at this example and I have written this code.
public static void main(String[] args) throws Exception {
final ByteBuddy bb = new ByteBuddy();
TypeDescription.Generic g1 = TypeDescription.Generic.Builder.rawType(Object.class).build();
final InstrumentedType typeDescrB = InstrumentedType.Default.of("B", g1, Modifier.PUBLIC);
final DynamicType.Unloaded<Object> madeA = bb
.subclass(Object.class)
.name("A")
.defineField("theB", typeDescrB, Modifier.PUBLIC).make();
final DynamicType.Unloaded<Object> madeB = bb.subclass(Object.class)
.name("B")
.defineField("theA", madeA.getTypeDescription()).make();
Class a = madeA.include(madeB)
.load(Test.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
for (Field f : a.getFields()) {
System.out.println(f + "|" + f.getType().getName());
}
System.out.println("====");
for (Field f : a.getField("theB").getType().getFields()) {
System.out.println(f + "|" + f.getType().getName());
}
}
After running the code I get this results
public B A.theB|B
====
Process finished with exit code 0
which means the Class B does not contain the field a. Does anybody know what is the problem?

I'm guessing that what you're seeing is just a mistake in your code.
With this code:
final DynamicType.Unloaded<Object> madeB = bb.subclass(Object.class)
.name("B")
.defineField("theA", madeA.getTypeDescription()).make();
…you have made the field non-public (note that you specified PUBLIC for the other field, but not here). Then with this code:
for (Field f : a.getField("theB").getType().getFields()) {
System.out.println(f + "|" + f.getType().getName());
}
…you have asked for only public fields. Perhaps you meant getDeclaredFields()?

Related

In Linked list how to produce value

I would like to repeatedly enter a number that is added to a linked list.
But there's an error in the code at line x = new Node():
No enclosing instance of type Main is accessible. Must qualify the allocation with an enclosing instance of type Main (e.g. x.new A() where x is an instance of Main).
Is there a way to fix my code?
static Node head;
static Node p;
static Node q;
static Node x;
class Node {
int data;
Node next;
public Node link;
// Constructor to create a new node
// Next is by default initialized
// as null
Node(int d) {
data = d;
next = null;
}
public Node() {
// TODO Auto-generated constructor stub
}
}
Two issues:
class Node should either be declared as static, or be moved to a separate file.
p = x should happen outside the else block, since it should get this value also when the if condition was true:
if(head == null) {
head = x;
} else {
p.link = x;
}
p = x;
Some remarks:
If you really want to use the Node constructor without arguments, then it is better to define explicitly what the new Node's properties should be:
public Node() {
data = 0;
next = null;
}
However, it would be better to not have this constructor signature at all, and only construct the object using the data as argument:
if(num != -999){
x = new Node(num);
...and now you don't need to do any of this any more:
x.data = num;
x.link = null;
The inner Node class is not static, meaning it belongs to a specific instance of the enclosing Main class. Since it doesn't refer to any instance methods this seems like it was not done intentionally. Make the class itself static (i.e., static class Node {) and you should be fine.
First, the class Node cannot be referenced from a static context. To fix this, make it static or move it to its own file. Second, the null pointer exception happens since you don't assign p in the special case where the list is empty.
Overall, I suggest that you clean up your class and use a more structured approach. Rename p to last to make it clear that this is a reference to the last element of the list. Move the functionality to add a node into its own method to make the code more readable. Use next in the Node class to point to the next node instead of link. Create an instance of the class where your head and last reference is defined and make them private. Use break inside the loop to only define the magic number (-999) once and exit the loop when it is entered.
The whole class could look like this:
public class CustomLinkedList {
private Node head = null;
private Node last = null;
static class Node {
int data;
Node next = null;
}
public void add(int num) {
Node x = new Node();
x.data = num;
if (this.head == null) {
this.head = x;
} else {
this.last.next = x;
}
this.last = x;
}
public static void main(String[] args) {
CustomLinkedList list = new CustomLinkedList();
int count = 0;
do {
try {
BufferedReader dataIn = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter number " + (++count) + ": ");
String strNum = dataIn.readLine();
int num = Integer.parseInt(strNum);
if (num != -999) {
list.add(num);
} else {
break; // exit loop
}
} catch (IOException e) {
System.out.print(e.getMessage());
}
} while (true);
}
}

Read different values from Excel file every time when test case runs

I have create a excel file with some codes and I am using RepeatRule class to execute my test case 100 times in one class. I need to use different 100 codes every time the test will run rather than using the same code again and again. Below is my code
#Test
#Repeat(2)
public void Test() throws Exception {
Success.setUp();
Success.allowcokkies();
//Success.Ecoomerecemain();
File source = new File("/Users/test/Downloads/Voucher-codes.xlsx");
FileInputStream input = new FileInputStream(source); // Read Excel Data
XSSFWorkbook wb = new XSSFWorkbook(input);
XSSFSheet sheet = wb.getSheetAt(0);
int noOfColumns = sheet.getRow(0).getLastCellNum();
System.out.println(noOfColumns);
String[] Headers = new String[noOfColumns];
int j=0;
Headers[j] = sheet.getRow(0).getCell(j).getStringCellValue();
Success.getDriver().findElement(By.xpath("//*[#id=\"code\"]")).sendKeys(sheet.getRow(0).getCell(j).getStringCellValue());// Enter Coupon
Thread.sleep(2000);
}
#After
public void testdown()
{
Success.getDriver().quit();
This is repeat class code:
public class RepeatRule implements TestRule {
public static class RepeatStatement extends Statement {
private final Statement statement;
private final int repeat;
public RepeatStatement(Statement statement, int repeat) {
this.statement = statement;
this.repeat = repeat;
}
#Override
public void evaluate() throws Throwable {
for (int i = 0; i < repeat; i++) {
statement.evaluate();
}
}
}
#Override
public Statement apply(Statement statement, Description description) {
Statement result = statement;
Repeat repeat = description.getAnnotation(Repeat.class);
if (repeat != null) {
int times = repeat.value();
result = new RepeatStatement(statement, times);
}
return result;
}
}
How can I read different codes every time while using Repeat rule?
The easy way to do this is a JUnit 5 parameterized test. Save your Excel sheet as csv and use the following test method:
#ParameterizedTest
#CsvFileSource(resources = "/Users/test/Downloads/Voucher-codes.csv", numLinesToSkip = 1)
void testVoucher(String coupon) {
...
Success.getDriver().findElement(By.xpath("//*[#id=\"code\"]")).sendKeys(coupon);// Enter Coupon
...
}
Parameterized tests are possible with JUnit 4 as well. An example is described in the JUnit Wiki. You can even use the Excel sheet as a data provider with your POI code.
Another solution would be using #BeforeEach, where you could update a coupon field couponIndex in your test class and access the right row by the value of this field.
Success.getDriver().findElement(By.xpath("//*[#id=\"code\"]")).sendKeys(sheet.getRow(couponIndex).getCell(j).getStringCellValue());// Enter Coupon
I would recommend using a parameterized test.

How to define point cuts for a sequence of method(s)?

For example if I have 3 classes,
class A {
public void doA() {
/* do something */
}
}
class B {
public void doB() {
A a = new A();
a.doA();
}
}
class MyClass {
public static void main(String args[]) {
B b = new B();
b.doB();
}
}
Now I want to define a point cut for flow doB() -> doA(), like if doB() calls doA() grab parameters from class A and class B and do something in aspect method. Could someone help me out.
Let me slightly extend your sample code in order to make you understand what my solution does and what it cannot do:
class A {
public void doA() {}
}
class B {
public void doB() {
new A().doA();
new C().doC();
}
}
class C {
public void doC() {
new A().doA();
}
}
class MyClass {
public static void main(String args[]) {
new A().doA(); // should not be captured
new B().doB(); // should be captured
}
}
As you can see, there is a new class C now and we have three control flows now:
MyClass.main -> A.doA
MyClass.main -> B.doB -> A.doA
MyClass.main -> B.doB -> C.doC -> A.doA
You want to exclude #1 and capture #2, but what about #3? In this case a.doA is called indirectly from B.doB via C.doC. My solution also captures this indirect case. If this is fine for you or it does not happen in your code base, you can use my solution. Otherwise things would get a little more complicated and you would need to inspect the call stack. Tell me if you need to exclude #2, and I will extend my answer, but the solution will not look as simple as this one, I can promise.
Now here is the aspect:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class ControlFlowInterceptor {
#Before("execution(void A.doA()) && target(a) && cflow(execution(void B.doB()) && target(b))")
public void advice(JoinPoint thisJoinPoint, A a, B b) {
System.out.println(thisJoinPoint);
System.out.println(" " + a);
System.out.println(" " + b);
}
}
The console output looks like this:
execution(void A.doA())
A#7b19f779
B#65c66812
execution(void A.doA())
A#4df2868
B#65c66812
Please note that we have the same B object ID in both outputs, but because C.doC creates an new A object, we have two different A object IDs.

jackson custom serialization with filtering

I need to customize serialization of a POJO in Jackson so that I can apply filter on the properties based on user input
I applied the following annotations on the POJO.
#JsonFilter("userFilter")
#JsonSerialize(using = UserSerializer.class)
The custom serializer class is as below.
public class UserSerializer extends JsonSerializer<User> {
#Override
public void serialize(User value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
SimpleFilterProvider sfp = new SimpleFilterProvider();
// create a set that holds name of User properties that must be serialized
Set userFilterSet = new HashSet<String>();
userFilterSet.add("firstName");
userFilterSet.add("corporateOrgs");
userFilterSet.add("rights");
userFilterSet.add("requirements");
sfp.addFilter("userFilter",SimpleBeanPropertyFilter.filterOutAllExcept(userFilterSet));
// create an objectwriter which will apply the filters
ObjectWriter writer = mapper.writer(sfp);
String json = writer.writeValueAsString(value);
}
}
I can see that Jackson is trying to serialize the POJO using the custom serializer defined. However it ends up in infinite recursion/stackoverflow as writer.writeValueAsString(value) ends up calling the custom serializer again.
Obviously I have not got some basic stuff right here. If the filtering is done outside the serialize method (for example in a method called from main() ), filtering works as expected.
can anyone please provide insight/link to documentation on how to make use of custom serialization to leverage filtering.
Fields can be filtered out with JsonFilter, or you can create a custom JsonSerialize serializer that writes out only certain fields.
Independent of the use of a JsonFilter, the attempt to recursively reserialize the same object to be serialized (first parameter of the overwritten serialize method) in a user-defined serializer with an object mapper will result in an infinite loop. Instead, in a custom serializer you would rather use the JsonGenerator methods (second parameter of the overridden serialize method) to write out field name/values.
In the following answer both variants (#JsonFilter and #JsonSerialize) are demonstrated, where only a part of the available fields are serialized to JSON.
#JsonFilter
To apply filters to properties based on user input, you do not need to extend JsonSerializer. Instead, you annotate the POJO with JsonFilter and just apply the filtering.
A self-contained example based on your code would look like this:
package com.software7.test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Main m = new Main();
try {
m.serialize();
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
void serialize() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
SimpleFilterProvider sfp = new SimpleFilterProvider();
Set<String> userFilterSet = new HashSet<>();
userFilterSet.add("firstName");
userFilterSet.add("corporateOrgs");
userFilterSet.add("rights");
userFilterSet.add("requirements");
sfp.addFilter("UserFilter",
SimpleBeanPropertyFilter.filterOutAllExcept(userFilterSet));
mapper.setFilterProvider(sfp);
User user = new User("Brownrigg", "Don", "none", "+rwx", "n/a",
"some", "superfluous", "properties");
System.out.println(user);
System.out.println(">>>> serializing >>>>");
String s = mapper.writeValueAsString(user);
System.out.println(s);
}
}
User POJO
package com.software7.test;
import com.fasterxml.jackson.annotation.JsonFilter;
#JsonFilter("UserFilter")
public class User {
public String lastName;
public String firstName;
public String corporateOrgs;
public String rights;
public String requirements;
public String a, b, c;
public User(String lastName, String firstName, String corporateOrgs, String rights, String requirements,
String a, String b, String c) {
this.lastName = lastName;
this.firstName = firstName;
this.corporateOrgs = corporateOrgs;
this.rights = rights;
this.requirements = requirements;
this.a = a;
this.b = b;
this.c = c;
}
#Override
public String toString() {
return "User{" +
"lastName='" + lastName + '\'' +
", firstName='" + firstName + '\'' +
", corporateOrgs='" + corporateOrgs + '\'' +
", rights='" + rights + '\'' +
", requirements='" + requirements + '\'' +
", a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
'}';
}
}
Test
The debug output of the above program would look like this:
User{lastName='Brownrigg', firstName='Don', corporateOrgs='none', rights='+rwx', requirements='n/a', a='some', b='superfluous', c='properties'}
>>>> serializing >>>>
{"firstName":"Don","corporateOrgs":"none","rights":"+rwx","requirements":"n/a"}
The test is successful! As you can see, the properties lastName, a, b and c are removed.
#JsonSerialize Alternative
If you want to use a customer serializer instead you can do like so:
Replace the annotation:
#JsonFilter("UserFilter")
with
#JsonSerialize(using = UserSerializer.class)
but do not use both.
The UserSerializer class could look like this:
package com.software7.test;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
public class UserSerializer extends JsonSerializer<User> {
#Override
public void serialize(User user, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException, JsonProcessingException {
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectField("firstName", user.firstName);
jsonGenerator.writeObjectField("corporateOrgs", user.corporateOrgs);
jsonGenerator.writeObjectField("rights", user.rights);
jsonGenerator.writeObjectField("requirements", user.requirements);
jsonGenerator.writeEndObject();
}
}
Finally, the serialization method would look like this:
void serialize() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
User user = new User("Brownrigg", "Don", "none", "+rwx", "n/a",
"some", "superfluous", "properties");
System.out.println(user);
System.out.println(">>>> serializing >>>>");
String s = mapper.writeValueAsString(user);
System.out.println(s);
}
The result would be the same in this example. Which variant is better suited depends on the specific use case or personal preferences.

SCJP6 var arg issue from Kathie siera

please help me to sort out the issues.because my answer getting different from Kathie siera book answer.for the below code i get compile error because of redeclaration to sifter(BB .
But in the book answer is "-434"
class AA{}
class BB extends AA{
}
public class ComingThru {
static String s="-";
public static void main(String args[])
{
AA aa []=new AA[2];
BB bb []=new BB[2];
sifter(aa);
System.out.println(s);
sifter(bb);
sifter(7);
System.out.println(s);
}
static void sifter(AA... a2)
{
s+="1";
}
static void sifter(BB... a2)
{
s+="2";
}
static void sifter(BB[] a3)
{
s+="2";
}
static void sifter(Object o){
s+="4";
}
}
I've checked the book, the arguments for the first two functions is not AA or BB, is an array of AA or BB:
It should be like this:
static void sifter(AA[] ... a2) {s += "1"}
static void sifter(BB[] ... b1) {s += "2"}
Attention that AA[] means that it accepts an array of array(AA[]) but not an array of AA.
So the answer in the book is correct.
PS:
In your code, it's normal that there is a compile error. Since you define both sifter(BB ... b1) and sifter(BB[] b2), the compiler cannot tell which one to choose if you pass an array of BB as argument.