I have below the class.
SomeClass.java
public class SomeClass {
private String name;
private String id;
private String access;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAccess() {
return access;
}
public void setAccess(String access) {
this.access = access;
}
public void doSomeFunctionality(){
//does some logic using name and id
}
}
Now I have to expose only few methods of above class to clients. I can do as below.
SomeOtherClass.java
public class SomeOtherClass {
private SomeClass someClass = new SomeClass();
public void setName(String name) {
someClass.setName(name);
}
public void setId(String id) {
this.setId(id);
}
}
By doing like above i can restrict one method not accessible to clients and am exposing only required methods. Now client instantiates SomeClass and populates the data into someClass property of SomeOtherClass.java.
But now how can i get the populated data from SomeOtherClass.java?
public SomeClass getSomeClass() {
return someClass;
}
If i provide getter method to get SomeClass in SomeOtherClass.java like above then even clients can also access it which i dont want to do.
But if i can get populated someClass instance directly then i can simply call doSomeFunctionality() on the same instance. like getSomeClass().doSomeFunctionality();
How can i overcome above scenario?
Thanks!
Your question seems confused, but I think this is the answer you are looking for,
Your approach to letting the client get the information should be exactly the same as letting them set it. You should not provide access to the inner SomeClass - that defeats the whole point. So if you want to provide both read and write access to only the name property, your outer class should look like:
public class SomeOtherClass {
private SomeClass someClass = new SomeClass();
public void setName(String name) {
someClass.setName(name);
}
public String getName() {
return someClass.getName();
}
}
You don't have to make the properties they can get the same as the properties they can set. You could also allow them to 'get' the ID, for example, but not set it. If you want them to have access to all the properties, provide getters for all properties in SomeOtherClass. If that is the case you might want to consider creating an interface which specifies all the getter methods and is implemented by both SomeClass and SomeOtherClass, with both classes also implementing the setter methods they require.
There are other architectural approaches if you always want to provide full 'read' access but restricted 'write' access, which we can go into if you ask.
If you create an interface that is implemented by the class that will be used by the client, but then the client obtains its reference to the instantiation of the class using the interface, even if you have public properties, members, ...etc., the client will only see those provided/defined by the interface.
Don't return the SomeClass object in a getter, just create a getter for the field(s) you want to make available:
public String getName() {
return someClass.getName();
}
I would suggest thinking about how you would separately test the pieces involved here. If we look at SomeOtherClass, right away we notice that it has a dependency on SomeClass--this is fine. Unfortunately, you hardwire the dependency to SomeClass by using the new operator. If you used a dependency injection framework (e.g., Spring or Guice) you could simply have the framework provide a fully configured instance of SomeClass to SomeOtherClass so that the instance could be used directly and SomeClass is no longer in the business of creating its own dependencies, but rather it goes about doing its useful work. Calling new on SomeClass in SomeOtherClass impedes your ability to test SomeOtherClass independently of SomeClass--you'll be integration testing unless you employ something like PowerMock, which really is better used in emergency situations like when you can't control third-party code. Hope it helps! P.S. all those setters and none for your dependency on SomeClass!
Related
#Configuration
public class Product {
#Bean("xyz")
public String getMethod() {
return "abc";
}
}
#Component
public class Test {
String b;
Test(String xyz) {
this.b = xyz;
}
}
Is this any harm with this approach? I am trying to make change in the existing code where I am replacing the #Value with the getter as the method parameter. As I don't want to change the structure of the existing code I am trying to inject the method as bean as a replacement to #Value.
I suggest you to keep the #Value annotation instead of the whole #Bean configurations.
Why?
What if the getMethod()'s returned value needs to be changed very often? Everytime when you're changing something in the Product class, during build time it needs to be recompiled. What happens if the project is getting bigger and you're using this approach? It leads to longer build time and the more important thing is that this solution is not intuitive and it's hard to keep it clean. Don't think about complex solutions only to make the code look fancy. When you need to inject String values, the easiest approach is to create properties files (which won't get recompiled) and use the #Value annotation.
Now, if you want to add new methods without changing the structure of the existing code there are some patterns which you can apply like decorator pattern.
The main idea is simple: you're creating a decorator class which has an object of the type you need.
The easiest example (which you'll find everywhere on the internet) is the classic Shape example:
public interface Shape {
String someMethod();
}
#Component
public class CustomShape implements Shape { //implement the method here }
And here is the decorator:
public interface ShapeDecorator {
String someMethodExtended();
void someExtraMethod();
}
#Component
public class CustomShapeDecorator implements ShapeDecorator{
#Autowired
// #Qualifier - optional (only if you have more Shape implementations)
private Shape shape;
// now you can either:
// 1. provide new methods
#Override
public void someExtraMethod(){
System.out.println("Hello world!");
}
// 2. or you can EXTEND the Shape's "someMethod()" implementation
#Override
public String someMethodExtended(){
String oldString = this.shape.someMethod();
return oldString + " EXTENDED";
}
}
I want to write a function that, given an arbitrary java bean as an argument, returns an object that is a copy of that bean but that belongs to an anonymous subclass of the bean's type that contains an additional property. Let me illustrate with an example of what I have so far:
Foo.java:
import lombok.Data;
import lombol.AllArgsConstructor;
#Data
#AllArgsConstructor
public class Foo {
private String bar;
private String baz;
}
Garply.java:
public class Garply {
Foo fooWithQux(Foo foo, String quxVal) {
return new Foo(foo.bar, foo.baz) {
private String qux;
public String getQux() {
return quxVal;
}
};
}
}
This seems silly because I can never actually call getQux(), but a tool I work with uses reflection to successfully find the qux property and do what I want with it.
My issue is that I don't want to have separate fooWithQux() functions for each type that I want to be able to add the qux property to. Ideally I'd have something like beanWithQux() that accepts objects of arbitrary type. I think I could make this work with something like the following:
public T beanWithQux<T>(T bean, String quxVal) {
class BeanWithQux extends T {
private String qux;
BeanWithQux(T bean, String quxVal) {
// Here's where I'd like to copy all of the properties
// from the Bean into the BeanWithQux
qux = quxVal;
}
public getQux() {
return qux;
}
}
return BeanWithQux(bean, quxVal);
}
Here's where I'm stuck. I don't know to copy all of the properties from the given object into my new object. Anyone have ideas? Ideally there would be something I could do using lombok (I control the Foo class and can add annotations like #Builder if need be) as opposed to writing a bunch of reflection magic myself.
Thanks!
I think in this case using runtime bytecode weaving is a better approach, since you don't need to call the methods in your own codebase.
Lets say we have following class:
package com.porphyrie.examples;
public class TestExample {
private String name;
private int id;
public TestExample() {
setName("testExample");
setId(3);
}
public String getName() {
return name;
}
private void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
private void setId(int id) {
this.id = id;
}
}
How should I test this class? Since eclipse wants only to test the public methods, how I should test the getters without setting the setters? Is it valid to set the private setter-methods in the class above to public only for testing purposes?
Thanks for any help...
Your example code is a good example of code not written to enable easy unit testing. If you adopt the mindset that you have to design/structure/write your code in a way that makes it easier for you to test, then you shouldn't have these questions. Short answer, yes, expose setters as public to enable your testing, or package/default scope if you don't want the setters part of the public api.
Alternatively, you could add another constructor with parameters to set the values for you when you create an instance.
You should not make setters private as the purpose of setters is for the programmer implementing a class to set values that they want to into the fields of the class. It is kind of redundant to have private setters as the fields are already private. If you don't what the fields to be mutated then leave the fields as private and don't create setters for these fields.
So yes is the answer to your question.
If you have a reason for not making your setters public, then you can use a parameterized contructor which initiates the fields with values passed as parameters when an object of this class is created and calling the parameterized constructor when instantiating the object.
No your private method can't be called from your unit test cases. so either you have to make it public or default or protected(if you have put it in the same package). You usually don't test private methods because they can only (normally) be tested indirectly through another public method. When you're test driving and make private methods then they are usually a result of an "extract method" refactoring and are already by then tested indirectly.
I have example to ilustrate my problem:
package com.example;
public class ExamplePublicClass {
public void doSomething() {
// a lot of code
String message = new ExamplePublicClass.MessageBuilder().withName("someName").build();
// a lot of code
}
private static class MessageBuilder {
private String name;
public MessageBuilder withName(String name) {
this.name = name;
return this;
}
public String build() {
return this.name + 1;
}
}
}
doSomething() method doing a lot o things and there is a lot o legacy code but it works and I don't want to touch her.
Only what I want to do is a change a builder to creating a log message and write a test for him. The problem is the fact that MessageBuilder is a private class and is doesn't make sense to change it to public.In additonal I don't want to changing visibility through reflection.
I added a class for test in the same package
package com.example;
import org.junit.Test;
public class MessageBuilderTest {
#Test
public void testMessageBuilder() {
String s = MessageBuilder..
}
}
but I don't have access to this private class :(
Working code is located in
src/main/java
and test code is located
src/test/java
What do you thing? Should I change project structure to
src
|/main/java
|/test/java
?
Or exist better solution?
Best Regards
T
I've always considered modifying access via Reflection as a bad practice, which is useful for nothing but understanding that there is something wrong with the design. :-)
In general, a unit test is intended to test the public (or actually, the non-private) interface of a class. All private methods are implementation detail that you would not expect to test explicitly.
When you have private methods in a class and you want to Unit-test them, this is considered as a sign for a code smell, because the class can be simplified/modified so that the private units are unit-testable.
You can do one of these:
refactor the nested private static class to a top-level one and mark it as package-private accessible.
provide a public (or, at least, non-private) access to the private units that you want to test.
You can also take a look on this thread, where the topic is discussed more extensively.
Is there a way to use abstract or annotated class as MXBean descriptor? I have interface like:
#MXBean
public interface Peer {
public String getName();
}
and want that MXBean to be combined in class with more local-side-only methods like:
public class PeerCombinedMXBean {
// Expose this as MXBean attribute
public String getName() { ... }
// This method is local-instance-oriented
public boolean isValid() { ... }
}
I need model like above to avoid chain-in proxy object instead to use complex half-proxified instance like:
PeerCombinedMXBean peer = JMX.newMXBeanProxy(connection, name, PeerCombinedMXBean.class);
if (peer.isValid()) System.out.println(peer.getName());
Edit
This question is related to java.net article. What is they progress? Can I use MBeans with annotation safely now?
What I ended up doing for this was writing a custom annotation that you place on a method or property. Then, I implemented the DynamicMBean interface in such a way that it parsed out the annotations on the class in question and then registers them with the PlatformMBeanServer. As far as I know, there are no public implementations of this available, I also searched extensively about this topic before I just did it myself.
For example, here is the class that I wish to manage from JConsole:
public class Foo
{
// In JMX Console
#Managed
private boolean isBar;
// Not in JMX Console
private boolean isFoo;
// In JMX Console
#Managed
public String getClassName()
{
return Foo.class.getName();
}
}
Then, when my application starts up, I register an instance of this class using my implementation of DynamicMBean and parse out the annotations.