Having problems compiling sub classes of a base class that I've defined that has a single method and each sub class implements the abstract base method, but javac is saying that they don't even though it is quite clearly defined in the sub class.
DbModel.java (the base class)
package com.manodestra.db;
import java.sql.ResultSet;
import java.sql.SQLException;
public abstract class DbModel<T extends DbModel> extends Model {
abstract T newInstance(ResultSet rs) throws SQLException;
}
DbModel extends Model, which only has a generic toString method.
MenuPermissions.java (the sub class)
package com.manodestra.csa.db.model.configNew;
import com.manodestra.db.DbModel;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
public class MenuPermissions extends DbModel<MenuPermissions> {
private final String menuId;
private final String userLevel;
public MenuPermissions(
String menuId,
String userLevel
) {
this.menuId = menuId;
this.userLevel = userLevel;
}
public String getMenuId() {
return this.menuId;
}
public String getUserLevel() {
return this.userLevel;
}
public MenuPermissions newInstance(ResultSet rs) throws SQLException {
return new MenuPermissions(
rs.getString("menu_id"),
rs.getString("user_level")
);
}
}
Compilation Error
[javac] Compiling 487 source files to C:\Media\Code\manodestra_java\bin
[javac] C:\Media\Code\manodestra_java\src\com\manodestra\csa\db\model\configNew\MenuPermissions.java:10:
error: MenuPermissions is not abstract
and does not override abstract method newInstance(ResultSet) in DbModel
[javac] public class MenuPermissions extends DbModel<MenuPermissions> {
[javac] ^
Anyone see what the problem is here? I'm guessing that I'm overlooking something really simple.
Further info on requirements:
I'm building an entity framework that generates model objects from a given database. MenuPermissions above is one such model object (auto-generated by a class that I've written called GenerateModel). I want each model to have a method that will allow me to get a new instance of each objecct type based on a resultset, which will populate the object accordingly and return it. Ideally, it should be a static method, but I've tried it as a concrete method for the moment as I need to enforce its existence in each sub class of DbModel. Hope that makes sense.
Your abstract method newInstance has package access. I don't know if that was intended but if it is in a different package then you would get an error.
Edit:
So the abstract method in the parent class can not be resolved since it is not declared a public. A possible remedy is to add public to the method definition or move the child class into the same package as the parent class :-D
Related
I've seen few previous answers for the similar answers. Still I'm unable to understand as I'm new to this. Here my code below
package com.kishore.junitTestCases.innerClasses;
public class OuterClass {
String prefix = "Hello, ";
private class InnerClasss {
public String greet(String name) {
return prefix+name;
}
}
public String displayFromInnerClass() {
InnerClasss inner = new InnerClasss();
String greetText = inner.greet("Kishore");
System.out.println(greetText);
return greetText;
}
}
Is it possible to write a JunitTestCase without changing anything in the above code? I'm using PowerMockito. Here is my half constructed test case.
package com.kishore.junitTestCases.innerClasses;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
public class OuterClassTest {
OuterClass outerClass = new OuterClass();
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void displayFromInnerClassTest() throws Exception {
}
}
Note: Also could you recommend few best practices? Thank You.
You don't.
It is possible, with great pains, to obtain an instance of an inner class (if it implements a public interface that contains all the methods you need from it) - see Can PowerMock instantiate an inner class for test cases?. That way you could test inner class methods.
You can't however, to my knowledge, test outer class while mocking inner class. Inner class lifecycle is intrinsically connected to the outer class instance, and there is no mechanism to replace it.
That you want to highlights a problem in the code you wrote - if invocation of inner class method is not intrinsic part of the operation, if it makes sense to mock the inner class in order to test the outer class - than it should not be a private inner class, it should be an injected dependency, precicely because you can then mock and test them in isolation.
I'm attempting to make a Repository interface, that our business logic can use, with the idea that if we decide to change the data source that backs the repositories, that the business logic would not be affected. We have many clients that would be using this library, so we have begun making a suite of controllers that can be reused among clients. This is the repository interface:
package //redacted
import java.util.Collection;
import java.util.List;
public interface Repository<T extends Object, R extends RepositoryQuery<T>> {
T add(T entity);
Collection<T> add(Collection<T> entities);
void remove(T entity);
Collection<T> getAll();
T get(Integer id) throws InvalidEntryException;
List<T> get(Collection<Integer> ids);
List<T> query(R query);
List<T> query(T query);
}
This is the controller I'm having problems with:
package //redacted
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import /* redacted */.entities.pointbank.PointBankBalance;
import /* redacted */.entities.user.User;
import /* redacted */.queries.PendingPointsBalance;
import /* redacted */.repository.Repository;
import /* redacted */.repository.RepositoryQuery;
public class RetrievePendingPointBalance {
private Repository<PointBankBalance, ? extends RepositoryQuery<PointBankBalance>> repository;
private Constructor<? extends PendingPointsBalance> pendingQuery;
public RetrievePendingPointBalance(Repository<PointBankBalance, ? extends RepositoryQuery<PointBankBalance>> repository,
Constructor<? extends PendingPointsBalance> pendingQuery) {
this.repository = repository;
this.pendingQuery = pendingQuery;
}
public PointBankBalance execute(User user) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
PendingPointsBalance query = pendingQuery.newInstance();
query.setUser(user);
return repository.query(query).get(0);
}
}
I'm trying to create RepositoryQuery, which is what will be responsible for handling more than just CRUD operations. Here is the interface for that:
package //redacted
import java.util.List;
public interface RepositoryQuery<T extends Object> {
List<T> execute();
}
The idea there, is that each query can extend can extend the interface with setters for the parameters it will need. Then each implementation can extend that query interface with specifics of what it will need (example: setJdbcTemplate(...) )
On the controller above though, the line:
return repository.query(query).get(0);
is a compilation error, and I do not know why. Is my approach inherently flawed, or am I just missing something?
Full Error:
[ERROR] /Users/redacted/src/main/java/com/redacted/controllers/RetrievePendingPointBalance.java:[26,28] no suitable method found for query(com.redacted.queries.PendingPointsBalance)
method com.redated.repository.Repository.query(capture#1 of ? extends com.redated.repository.RepositoryQuery<com.redacted.entities.pointbank.PointBankBalance>) is not applicable
(argument mismatch; com.redacted.queries.PendingPointsBalance cannot be converted to capture#1 of ? extends com.redacted.repository.RepositoryQuery<com.redacted.entities.pointbank.PointBankBalance>)
method com.redacted.repository.Repository.query(com.redacted.entities.pointbank.PointBankBalance) is not applicable
(argument mismatch; com.redacted.queries.PendingPointsBalance cannot be converted to com.redacted.entities.pointbank.PointBankBalance)
And my error from Eclipse:
Edit: PointBankBalance interface
package //redacted
import com./* redacted */.entities.pointbank.PointBankBalance;
import com./* redacted */.entities.user.User;
import com./* redacted */.repository.RepositoryQuery;
public interface PendingPointsBalance extends RepositoryQuery<PointBankBalance> {
void setUser(User user);
}
Your problem is that the method takes an R and you defined R as ? extends RepositoryQuery<PointBankBalance> in the repository field declaration. It's uncertain which subclass ? refers to, so the compiler won't let you use a specific one. You could potentially set that field to an instance of Repository<PointBankBalance, AnotherPointsBalance>, in which case PendingPointsBalance wouldn't be a valid argument to its query method.
One way to fix it would be replacing Repository<PointBankBalance, ? extends RepositoryQuery<PointBankBalance>> with Repository<PointBankBalance, PendingPointsBalance>.
Or you could simplify things by removing the R parameter entirely:
public interface Repository<T extends Object> {
...
List<T> query(RepositoryQuery<T> query);
List<T> query(T query);
}
Then just replace Repository<PointBankBalance, ? extends RepositoryQuery<PointBankBalance>> with Repository<PointBankBalance>.
In the following code snippet I'm calling the method doStuff once on an instance of Subclass. However it is intercepted twice.
Note that doStuff was defined in the parent class SuperClass. If doStuff was defined in SubClass the interception logic would work as expected: only one interception.
Am I using Byte Buddy incorrectly?
package com.test;
import static net.bytebuddy.matcher.ElementMatchers.any;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
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.Builder;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import org.junit.Test;
public class ReproBugTest {
#Test
public void reproBug() {
new AgentBuilder.Default().type(nameStartsWith("com.test"))
.transform(new AgentBuilder.Transformer() {
#Override
public Builder<?> transform(
Builder<?> builder,
TypeDescription td) {
return builder.method(any())
.intercept(
MethodDelegation.to(MethodInterceptor.class));
}
})
.installOn(
ByteBuddyAgent.installOnOpenJDK());
SubClass subClass = new SubClass();
subClass.doStuff();
}
}
class SuperClass {
public void doStuff() {
System.out.println("Doing stuff...");
}
}
class SubClass extends SuperClass {
}
class MethodInterceptor {
#RuntimeType
public static Object intercept(#SuperCall Callable<?> zuper)
throws Exception {
// Intercepted twice, bug?
System.out.println("Intercepted");
Object returnValue = zuper.call();
return returnValue;
}
}
You are intercepting the method call for every type, i.e. for both Subclass and SuperClass. You need to further specify your interceptor for what methods to intercept. In you case, you only want to intercept methods if they are declared by a given type.
This is easy to implement. Instead of builder.method(any()), you should intercept builder.method(isDeclaredBy(td)). This way, a method is only intercepted if it is declared by the intercepted type.
Finally, I can see from, your source code that you are using an older version of Byte Buddy. Version 0.7-rc6 runs stable, has additional features and fixes several bugs. (However, some APIs still need to be changed.)
I have a class like:
package com.example;
public abstract class AbstractClass<S> {
//stuffs
}
Then a class that extends it, and define the generic type as its own inner class:
package com.example2;
import com.example.AbstractClass;
import com.example2.MyObject.MyObjectInnerClass;
public class MyObject extends AbstractClass<MyObjectInnerClass> {
//other stuffs
public static class MyObjectInnerClass {
}
}
Why is needed the import of com.example2.MyObject.MyObjectInnerClass if it stays in the same file?
import com.example.AbstractClass;
import com.example2.MyObject.MyObjectInnerClass;
public class MyObject extends AbstractClass<MyObjectInnerClass> {
It is needed because the nested (not inner) class MyObjectInnerClass only exists with an unqualifed name inside the {, which comes after the use of it in the extendsclause.
A more conventional way of writing it would be:
import com.example.AbstractClass;
public class MyObject extends AbstractClass<MyObject .MyObjectInnerClass> {
Let's start by saying - it's not an inner class, it's a nested class (inner class is a non-static nested class).
That import is needed for two important reasons:
It needs to know which class do you mean - You could also have MyObjectInnerClass as a class in the same package as MyObject. Importless reference to such class would point to exactly that one.
That's what nested classes are for - to group classes in a logical hierarchical structure.
Note that it is customary to, instead of import, write MyObject.MyObjectInnerClass to put emphasis on the relationship between the two.
Pack.java imports pack.TestPack; but it cannot access it. I cannot understand why it cannot access the class despite the import.
Error
Pack.java:7: TestPack() is not public in pack.TestPack; cannot be accessed from outside package
System.out.println(new TestPack().getHello());
^
1 error
Pack.java
import pack.TestPack;
import java.io.*;
public class Pack
{
public static void main(String[] args){
System.out.println(new TestPack().getHello());
}
}
TestPack.java
package pack;
import java.util.*;
import java.io.*;
public class TestPack
{
private String hello="if you see me, you ar inside class TestPack";
public String getHello(){return hello;}
TestPack(){}
}
You should make TestPack's constructor public.
public class TestPack
{
private String hello="if you see me, you ar inside class TestPack";
public String getHello(){return hello;}
public TestPack(){}
}
The thing is, even though TestPack visibility is public, its parameterless constructor visibility is package (which is the visibility when you don't specify one explicitly).
package visibility means that classes in the same package will be able to see it. Since TestPack and Pack are not in the same package, Pack can't call TestPack's constructor.
In the way you are using getHello function, you may start thinking using static methods
public class TestPack
{
private static String hello="if you see me, you ar inside class TestPack";
public static String getHello(){return hello;}
private TestPack(){}
}
then you just will do:
public class Pack
{
public static void main(String[] args){
System.out.println(TestPack.getHello());
}
}
I suggest that you don't make the class public but make the constructor public and have folks use a public interface that your class implements. It is a good idea to start the API to your package to be public interfaces (and perhaps some public abstract classes) and hide your implementation classes by not marking them as public so that you can change these over time. You can then provide a public factory methods in your package which instantiate your package private class and return them as the interface types. Here is an interface which is public:
package stackoverflow;
public interface Widget {
public void doWidgetWork(String work);
}
Here is the implementation which is "package private". The compiler wont let code outside of the same package import nor use this class at all:
package stackoverflow;
/*package*/ class WidgetHidden implements Widget {
public WidgetHidden(String configOptionA, String configOptionB){
// ...
}
public WidgetHidden(){
// ...
}
public void doWidgetWork(String work)[
// ...
}
}
notice there that the second occurrence of the word /package/ is a comment (it is not legal in java to use that word there) but many programmers use such a comment in that position to show people that it was not an accident that the class is not public; it signifies that the developer really intended that the class is deliberately "package private". To let people instantiate the class from outside of your package you provide a static factory class (else an instance factory class):
package stackoverflow;
public class WidgetFactory {
public static Widget newInstance( String configOptionA, String configOptionB) {
return new Widget( String configOptionA, String configOptionB);
}
}
The whole point of the factory class is that it hides your internal classes (the ones you hide as package private). Over time you can change your factory classes to return new classes or rename or delete the WidgetHidden class.
Many frameworks indicate which classes other developers should not use by putting them into a package with the name "internal" in it. The public interfaces would be in the main package (e.g. "com.stackoverflow.widget") and the hidden classes into your internal package which only exposes public factory classes (e.g. "com.stackoverflow.widget.internal").
A variation on the theme is to not use a static method on the factory class; make it a regular method. The alternatives are called "static factories" or "instance factories" depending on whether the method is static or not. Not making the method static seems like more work for people using your package as they first have to instantiate your factory object before using it to create Widget. Where is helpful is when people might want to set some defaults for all widgets on the constructor of the factory then use the none static newInstance methods to specify anything beyond the defaults:
public class WidgetInstanceFactory {
private String defaultOptionA = null;
public WidgetInstanceFactory( String defaultOptionA ) {
this.defaultOptionA = defaultOptionA;
}
public Widget newInstance( String optionB ) {
return new WidgetHidden( this.defaultOptionA, optionB );
}
}
It is possible to get around package private protection using reflection to find and invoke the constructor. A really nice feature of the Spring framework it that it will instantiate classes that are not public even when there is no factory class (although it is more polite to provide factory classes which Spring is happy to use also). The following code will work:
package stackoverflow.other;
class TestInstantiate {
private Widget myWidget = null;
public TestInstantiate(){
this.myWidget = instantiatePackagePrivateClass("stackoverflow.WidgetHidden");
}
private Widget instantiatePackagePrivateClass(String className)
throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
#SuppressWarnings("unchecked")
Class<FileUploadSequence> clazz = (Class<Widget>) Class.forName(className);
Constructor<Widget> constructor = clazz.getConstructor(new Class[]{});
constructor.setAccessible(true);
Widget widget = (Widget) constructor.newInstance((Object[])null);
return widget;
}
}
In that example I used the no arguments constructor but clearly you can find and invoke the two string constructor using the same approach. Clearly such code gets around the intention of the programmer who wrote WidgetHidden; they wanted to hide it as they are likely to change it. Anyone who uses such a back door to manipulate the package private object should be aware that the class WidgetHidden is not part of the public API of the framework they are using so it likely to be deleted or changed without prior notice by the developer who wrote the package you are using. Renaming it to be WidgetInternal and putting it into an "internal" package make it every more the case you are telling people "do not uses". The JVM has optional security setting which prevent people from doing such tricks; but the person running the JVM has to configure it externally to dis-allow such tricks which is only useful when you want to run someone else code you don't trust and prevent it from pulling such tricks.
The book Effective Java by Josha Block 2nd Edition has a lot of discussion and examples and details of the pitfalls when trying to write a good API. It has a lot of detail to explain why you should always look to hide as many classes as you can with lots of other good "tricks of the trade".