Use JavaBeans to pass data between classes - java

A Piece of important information: The classes are all separate files and there are about 10 beans in total .
I am working on a project with multiple classes through which data must be passed.
I.e. a couple strings from say Class1 must be able to be used in Class2.
My program uses JavaBeans with set and get methods but if I set a bean in one class and try to get that data in another class I just get a null value returned.
I am unsure as to what the best method is, I have the beans nicely defined and would like to keep using them but I do not know how.
Could someone point me in the correct direction or give an example.
Thanks
Edit
Bean class snippet;
public class beans implements java.io.Serializable {
private String string1;
public String getstring1() {
return this.string1;
}
public void setstring1(String string1) {
this.string1 = string1;
}
And the setter code in say class1:
beans bean = new beans();
bean.setstring1("test");
And the class where the bet is "got", class2
beans bean = new beans();
String text = bean.getstring1();
That is pretty much how I am using the beans and they are not working as I want them to.

In your example you are creating a new bean in each class. The first and the second class have references to two different objects, that's why they can't access the same values.
There are multiple ways to solve this and it really depends on your application. But let me suggest one generic solution.
You can create a BeanRepository which is responsible for having references to all bean objects. Other classes then need to know the id of the bean and they can get a reference.
BeanRepository (notice the static methods):
public class BeanRepository {
private static Map<Integer, Bean> beanMap = new HashMap<Integer, Bean>();
public static void putBean(int id, Bean bean) {
beanMap.put(id, bean);
}
public static Bean getBean(int id) {
return beanMap.get(id);
}
}
The bean:
public class Bean {
private String name;
public Bean(String name) {
this.name = name;
}
public String whoAmI() {
return name;
}
}
Classes A and B:
public class ClassA {
private Bean bean;
public ClassA(int beanId) {
this.bean = BeanRepository.getBean(beanId);
}
public void test() {
System.out.println("I am ClassA. You are " + bean.whoAmI());
}
}
public class ClassB {
private Bean bean;
public ClassB(int beanId) {
this.bean = BeanRepository.getBean(beanId);
}
public void test() {
System.out.println("I am ClassB. You are " + bean.whoAmI());
}
}
Test method:
public class Main {
public static void main(String[] args) {
BeanRepository.putBean(1, new Bean("one"));
ClassA a = new ClassA(1);
ClassB b = new ClassB(1);
a.test();
b.test();
}
}

container I am very puzzled by your question. Are you referring to Enterprise Java Beans?
If you just mean ordinary JavaBeans just featuring get and set methods, the first thing I would advise is to learn how to use jUnit. Test your data bean first inorder to ensure it is working as intended.
Beside that if your class live within the same JVA (you only start a single java.exe / run a single application) everything should just work fine.
public class Data {
private String value;
public void set(String value) { this.value = value; }
public String get() { return this.value; }
}
public class ClassA {
Data data = new Data();
ClassA() { data.set("From ClassA"); }
}
public class ClassB {
Data data;
ClassB(Data data) { this.data = data; }
public void print() {
System.out.println(data.get());
}
}
public static void main(String args []) {
new ClassB(new ClassA().data).println();
}
This is a simple example using a data object to pass informations around.
Hope this is what you want to know.
[Update]
After you add some code I see the problem. As other users already wrote you are creating new objects (instances) every time. Since the string1 is a property of that class ever instance of it will have their own value.
The default example is a person. Creating a Person class with a property name (similar to your string1) you can create two persons (instances of class Person). You can now name every person individual.
Thats what Class mean. You specify the properties (instance variables) and behavior (methods) of instances (actual object) of that class.
If you want to share information you need a way to pass(!) an instance (object) of a Class to other instances. In Java different way exist. You can use static variables which are global (bound to the Class instead of an instance of a class), you can use singleton pattern (which employes the static variable), you can use ThreadLocal (a global store limited to the current thread), you may use managers / repositories storing objects and you pass the manager / repository objects along, you can use databases or you can use a dependency injector which is like a transparent object manager. Those are basically it.
For your use case I would use Singleton first.
public class MySingleton {
private static Bean myBean;
public static void setBean(Bean myBean) { MySingleton.myBean = myBean; }
public static Bean getBean() { return myBean; }
}
Using the class is straight forward:
Bean bean = new Bean();
bean.setString1("test");
MySingleton.setBean(bean);
Bean bean2 = MySingleton.getBean();
System.out.println(bean2.getString1()); //prints test
But beware this is the lazy way of doing things. Using static has some draw backs if you have a complex project especially when it comes to serialization, concurrency and reuse.

If you'se serializing/deserializing your classes, make sure that
string fields themselves are not marked as transient.
you're not using custom writeObject(ObjectOutputStream ) methods in your object where you forgot your string fields.
you're not cloning your class with custom clone() methods where you forgot your string field
you wrote setter and getter properly in the first place.
and things shoud work ;)

Related

How to return an object from different classes in Java?

I'm beginner in Java and I need help. I have several classes.
public class A{
private String name = "A";
public String getClassName(){
return "A";
}
public void editClassName(String name){
this.name = name;
}
}
public class B{
private String name = "B";
private int counter = 0;
public String showClassName(){
return "B";
}
public int getCount(){
return counter;
}
}
Such classes could be more. I also need to have some class witch can return an instance of asked class.
public class ClassSelector{
public static ??? getClassByName(String nameOfClass){
if(nameOfClass == "A"){ return new A();}
if(nameOfClass == "B"){ return new B();}
}
}
And here is a code that I want to use to get access to appropriate class:
ClassSelector.getClassByName("A").getClassName();
ClassSelector.getClassByName("B").showClassName();
I need to have an access to the instance of the class, and each instance can show it's unit methods that class has.
In this situation I don't get which return type I should use in the 'getClassByName' method.
I will very appreciate for help.
I would very much like to offer an alternative architecture if possible! It's not much different to what you have.
Firstly, we'll define some interface.
public interface Named {
String getName();
}
Now, this means you can have lots of concrete classes but provided they implement this interface, you'll know (and the Java compiler will know) that they have the getName method available to you.
Next, let's update your class to implement this interface.
public class A implements Named {
public String getName() {
return "A";
}
}
You could do this for classes B, C... and so on.
Now your method return type can be set to Named, that is:
public class ClassSelector{
public static Named getClassByName(String nameOfClass){
if(nameOfClass.equals("A")){ return new A();}
if(nameOfClass.equals("B")){ return new B();}
}
}
And you can access the response like so:
Named response = ClassSelector.getClassByName("A").getName();
As Eran suggested, it can be only of type Object, because they don't have a common superclass other than Object. If you don't want to work with Object class, you can create a body-less interface and implement it in both(or multiple classes) and that can be your return type.
After the call of the method, you can find the specific type of the returned object with instanceof;
What you are trying to do is called the Factory Pattern.
Assuming you are crating Widgets I suggest;
Introduce a Widget interface and have A and B implement Widget as per Christopher’s answer
Rename ClassSelector to WidgetFactory
Rename the method getClassByName to create, make it non-static and return Widget instances
This is more aligned with common Java name conventions and thus makes your code readily understandable by most developers.
If you want to keep your factory static it is of course possible but it may make your code less testable as it cannot be switched out for another factory in your tests. This is problematic if A and B are heavy weight objects that carries a lot of external dependencies that you may want to exclude.
If testability is a concern you may even consider making the factory implement a WidgetFactory interface...
First of all, please note that for string comparison you have not to use "==" (the problem is in nameOfClass == "A" and so on, I say it only for completeness).
I want suggest a solution based on reflection, that maybe could be more concise:
public interface IClass {
}
public class A implements IClass {
private String name = "A";
}
public class B implements IClass {
private String name = "B";
}
public class ClassSelector {
public static void main(String[] args) {
IClass obj = null;
try {
Class c = Class.forName("A");
obj = (IClass) c.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("Create object of type " + obj.getClass());
}
}
Thanks to all guys, who have answered my. Forgive me, when I create the first post, I made one mistake, which leads to misunderstanding what I mean. Now the code in the first post is better to show what I'm looking for.

Schema Generator for ApacheCayenne classes

I'm trying to use SPQR to generate GraphQL schema from a Cayenne generated class.
Cayenne class looks like this
public class MyCayenneClass {
public static final Property<Integer> A_PROPERTY = Property.create("aProperty", Integer.class);
public static final Property<Integer> ANOTHER_PROPERTY = Property.create("anotherProperty", String.class);
public void setAProperty(Integer aProperty) {
writeProperty("aProperty", aProperty);
}
public Integer getAProperty() {
return (Integer)readProperty("aProperty");
}
public void setAnotherProperty(String anotherProperty) {
writeProperty("anotherProperty", anotherProperty);
}
public String getAnotherProperty() {
return (String)readProperty("anotherProperty");
}
}
As the class isn't a simple POJO, SPQR throws an exception and the schema isn't generated.
Error: QUERY_ROOT fields must be an object with field names as keys or a function which returns such an object.
What's the best approach here (without modifying the cayenne class (i.e. annotating a method)?
GraphQLEndPoing.java
#WebServlet(urlPatterns = "/graphql")
public class GraphQLEndpoint extends SimpleGraphQLServlet {
public GraphQLEndpoint() {
super(buildSchema());
}
//This method used SPQR
private static GraphQLSchema buildSchema() {
GraphQLSchema schemaGenerator = new GraphQLSchemaGenerator()
.withOperationsFromSingletons(myRepository) //register the beans
.generate();
return schemaGenerator;
}
private static final MyRepository myRepository;
static {
myRepository= new MyRepository ();
}
}
MyRepository.java
public class MyRepository{
private MyLibService libService;
#GraphQLQuery
public MyCayenneClass find(Integer id) {
List<MyCayenneClass> myList= libService.fetchById(new Integer[] {id});
return myList.get(0);
}
}
*FYI. If I declare the schema. Code will work just fine
schema {
query: Query
}
type Query {
find(id: Int): MyCayenneClass
}
type ConcContract {
id: ID
aProperty: Int
anotherProperty: String
}
From SPQR's perspective, this isn't really different from a POJO, as SPQR cares only about the types.
By default, for all nested classes (MyCayenneClass in your case), everything that looks like a getter will be exposed. For top-level classes (MyRepository in your case), only annotated methods are exposed by default. And at least one top-level method must be exposed, otherwise you have an invalid schema.
The error, as it stands, just means not a single top-level query was discovered. I see the #GraphQLQuery annotation is commented out. Is that intentional? With the default config, this would not expose any query.
You can register a different ResolverBuilder, e.g. PublicResolverBuilder (or your own implementation/extension) if you want to expose un-annotated methods.
E.g.
generator.withOperationsFromSingleton(new MyRepository(), new PublicResolverBuilder())
This would expose all public methods from that class.
Here's a slightly simplified example I tried with v0.9.6 and seems to work as expected (I know you're using a rather old version from the error text).
public class MyRepository {
#GraphQLQuery //not commented out
public MyCayenneClass find(Integer in) {
return new MyCayenneClass();
}
}
// extends CayenneDataObject because I don't know where to get the
// writeProperty and readProperty from
// but shouldn't change anything from SPQR's perspective
public class MyCayenneClass extends CayenneDataObject {
public static final Property<Integer> A_PROPERTY = Property.create("aProperty", Integer.class);
public static final Property<String> ANOTHER_PROPERTY = Property.create("anotherProperty", String.class);
public void setAProperty(Integer aProperty) {
writeProperty("aProperty", aProperty);
}
public Integer getAProperty() {
return (Integer)readProperty("aProperty");
}
public void setAnotherProperty(String anotherProperty) {
writeProperty("anotherProperty", anotherProperty);
}
public String getAnotherProperty() {
return (String)readProperty("anotherProperty");
}
}
There's many more customizations you can apply, depending on what you end up needing, but from the question as it stands, it doesn't seem you need anything extra...
To override the ResolverBuilder used for nested classes, you have 2 options.
1) Register it globally, so all nested types use it:
generator.withNestedResolverBuilders(customBuilder)
2) Or per type:
.withNestedResolverBuildersForType(MyCayenneClass.class, new BeanResolverBuilder())
But this is very rarely needed...

how to toggle the right class for checkbox listener?

I have a GUI with a start button and a checkbox that creates multiple instances of Class A (A blueprint of my web service) based on given text input. The checkbox if checked writes some additional elements to the XML file (which is the main output of the entire application). Now I want to add an additional checkbox which will provide the GUI to create instances of Class B which extends Class A but provides some additional fields and logic.
My question is that how can I implement this required functionality?
Given there is a createMyXML() method in class C which is doing the same for hardcoded arguments as Class A or Class B for its methods, should I extend it to take one of the class as a parameter and create instances for required elements in the XML?
P.S. It is probable that this question may be too subjective but I wonder what could be the approach or the 'right way' to do it.
Class A Anatomy
public class A {
private String id;
private Vector<String> inputs;
private Vector<String> outputs;
//***Getters and Setters for above.***
}
Class C Anatomy
public class C {
void createMyXML(){
for (A a : this.parser.getAttributes()){
createFirstElement(A a);
createSecondElement(A a);
// Or (This behavior should be triggered by the checkbox)
createFirstElement(B b);
createSecondElement(B b);}
}
If I understand your question right, you want a way of creating different instances that would create XML files based on some logic that differs from class to class, preferably easily extendable later on.
In this case the Factory Design Pattern seems like a reasonable solution. You define an interface with the craeteMyXML() method:
public interface I {
public void createMyXML();
}
Add a class for each XML creation logic. In this example I've added two classes: A and B, which implement the I interface.
Class A:
import java.util.Vector;
public class A implements I {
private String id;
private Vector<String> inputs;
private Vector<String> outputs;
#Override
public void createMyXML() {
System.out.println("Create XML by the rules of A.");
}
/* Getters and setters and other methods needed*/
}
Class B:
public class B implements I {
#Override
public void createMyXML() {
System.out.println("Create XML by the rules of B.");
}
}
You can use an enum as a parameter for the factory based on which it creates instances. You can use other options as well, for example a String value or int, it depends on your solution. Here, I define the available instances as an enum:
public enum Instance {
A, B
}
The Factory class creates instance of A or B using the super-type I.
public class Factory {
public static I createInstance(Instance i) {
if (i == Instance.A) {
return new A();
} else if (i == Instance.B) {
return new B();
} else {
return null;
}
}
}
I'm adding a Test class to quickly test this solution, you can incorporate it in your project.
public class Test {
public static void main(String[] args) {
I a = Factory.createInstance(Instance.A);
I b = Factory.createInstance(Instance.B);
a.createMyXML();
b.createMyXML();
}
}
When you execute this, it will produce the output:
Create XML by the rules of A.
Create XML by the rules of B.

Can I have a single instance of Interface

In my Android application I have a class which gives me static string values; something like this:
public class VehicleInfo {
public static String getVehicleEnginePower(boolean isNew) {
return isNew ? "1800CC" : "1600CC";
}
}
Now I have another category, so I will have to pass another Boolean, and I will get the value I need. However, these categories will keep on increasing. So I looked into the Open/Closed principle which looks promising for quick enhancement. To ensure this I will make the VehicleInfo class as an Interface and then I will have other classes implement VehicleInfo.
public interface VehicleInfo {
String getVehicleEnginePower();
}
public class NewVehicle implements VehicleInfo {
#Override
public String getVehicleEnginePower() {
return "1800CC";
}
}
and the other category classes will also be something like this. In this way I will have to add another class for all the new categories.
The question I wanted to ask is: is there a way that I can have single instance of this interface? Because in the whole application flow, a user will only be able to see one category until he switches to another category.
I don't want to instantiate these classes at multiple points. To clarify my question, I want to do something like this at the start of my application:
if (isNew) {
VehicleInfo vehicleInfor = new NewVehicle();
}
And in the whole application, whenever I call VehicleInfo.getVehicleEnginePower, it should always return engine power from the NewVehicle class.
Is something like this possible? Or am I just being silly and I will have to instantiate this interface on multiple points?
Maybe you need a singleton here
public class VehicleInfoManager {
private static VehicleInfoManager INSTANCE = new VehicleInfoManager();
private VehicleInfo currentVehicleInfo;
public static VehicleInfoManager getInstance() {
return INSTANCE;
}
public void setCurrentVehicleInfo(VehicleInfo info) {
this.currentVehicleInfo = info;
}
public String getVehicleEnginePower() {
return this.currentVehicleInfo.getVehicleEnginePower();
}
private VehicleInfoManager() {
// Constructor private by default
}
}
Then you can call it from everywhere like this
VehicleInfoManager.getInstance().getVehicleEnginePower()
//Or set current info like this
VehicleInfoManager.getInstance().setCurrentVehicleInfo(new NewVehicle())
Just be careful as currentVehicleInfo is null by default so you need to handle null pointer cases.
If I understand your question correctly.
My solution to this would be Enum
public enum VehicleEnginePower {
NEW ("1800CC"),
OLD ("1600CC"),
private final String name;
private Modes(String s) {
name = s;
}
public String toString() {
return this.name;
}
}
Then you can do
if (isNew) {
String powerOfEngine = VehicleEnginePower.NEW.toString();
}

Java child class that can be refreshed with new instances of the parent class

I'm working with the Java AWS API to monitor some EC2 instances and on every refresh I need to query the service which returns a bunch of Instance objects (freshly constructed). I want to extend the functionality of these objects, I figure I can maintain a map of MyInstance objects which can be refreshed with the new Instances on each poll.
Now I could easily do this with a simple wrapper class that holds the original Instance as a property the issue is I would like to keep access to the base Instance API as I already use these functions in my code. Would it be possible to replace only the super-class parts of an instantiated object? Contrived example of what I'm going for:
class Instance {
protected int prop;
public Instance(int prop) {
this.prop = prop;
}
}
class MyInstance extends Instance {
protected int prop2;
public MyInstance(int prop, int prop2) {
super(prop);
this.prop2 = prop2;
}
}
MyInstance foo = new MyInstance(1, 2);
Instance foster = new Instance(3);
//what i want to do
foo.adoptedBy(foster);
//with the result that foo.prop == 3
Obviously this example would be trivial to transform but in my actual case there are far more properties that need to be transferred. Can Reflection do this? What kind of performance impact am I looking at if I use Reflection for 10 of these every second? Thanks for reading!
The best solution is to combine both your ideas:
Wrap the original Instance in a class that extends the Instance class. (In the constructor of the child class, you can create a new Instance object and set it)
Delegate all methods to the wrapped instance (and add new properties)
In your foster method, you simply change the wrapped Instance.
class Instance {
private int prop;
public Instance(int prop) {
this.prop = prop;
}
public int getProp() {
return prop;
}
}
class MyInstance extends Instance {
private Instance delegate;
private int prop2;
public MyInstance(Instance delegate, int prop2) {
super(prop);
this.delegate = delegate;
this.prop2 = prop2;
}
#Override
public int getProp() {
return delegate.getProp();
}
public int getProp2() {
return prop2;
}
public void foster(Instance i) {
delegate = i;
}
}
MyInstance foo = new MyInstance(1, 2);
Instance foster = new Instance(3);
//what i want to do
foo.adoptedBy(foster);
//with the result that foo.getProp() == 3

Categories

Resources