Make Spring Service Classes Final? - java

Can I make the spring service classes final? Is there any harm doing that? Nobody is going to extend the class. Is there any issue?
public final class MyService {
// Depedencies go here.
}

Don't make them final. If you use any AOP (including transaction support) on concrete classes, spring will use CGLIB to dynamically extend your class in order to make a proxy. And the requirement for CGLIB to work is to have your classes non-final. Otherwise an exception will be thrown.

Spring will create a JDK dynamic proxy rather than a CGLIB proxy if the following are true:
aop:config has proxy-target-classes set to false
Any other namespace configurations (e.g. tx:transaction-management) also have proxy-target-classes set to false
Your class implements an interface
If all three are true, then you can declare the class final. (You can even make the class package-private and the constructor private if you like, Spring will be able to instantiate it).
Otherwise, Spring will create a CGLIB proxy. You can still declare the class final (assuming it is not decorated with #Repository and you do not have a PersistenceExceptionPostBeanProcessor declared) if there are no public methods in the bean. Once you have a single public method, you cannot declare the class final with CBLIB proxying. (Note: you must have at least a package-private, no-argument constructor when proxying via CGLIB).
When is the above useful? Say you have a service interface (all services should generally have interfaces) with an implementation bean that is package private. The service is using JDK dynamic proxying. So, it can be final and non-visible outside the package, leaking fewer implementation details. Say the service needs a data access object. If no other service uses this DAO, why make it or any of its methods public? If all the methods on the DAO are package-private, the service implementation can still wire the DAO in and use its methods. From outside the package, callers only see the interface (a good thing) and any types that are used in the interface signature.
Finally (no pun intended), make a class final whenever you can. Concrete inheritance is both often confusing an abused (see fragile base problem). Final classes also allow some compiler optimizations.

Related

Avoiding default interface implementation for #Bean

Let's say
I have integration tests, therefore there is an ApplicationContextIntegrationTests class that contains dummy beans (dependencies on other services) for initializing the app context for integration profile like this:
#Bean
public MyService myService(Proc proc) {
return new MyServiceImp();
}
I have an interface MyInterfaceA with 20 methods (the code is autogenerated based on the definition in api.yaml), I cannot implement it and I don't have access to the implementation. This interface (well, it is an implementation) also should be inserted in the application context. Obviously, I need to implement all interface methods in order to insert that bean and it leads to messy code with default methods implementations on 50 lines. Moreover, I need to insert 3 interfaces.
Is there a way to avoid that huge amount of code?
I have found that Lombok provides a #Delegate annotation which is used in similar situations, but it is appliable only on fields, whereas I need to deal with methods (bcs of #Bean).
Is this generated class that implements MyInterfaceA also a bean? If so, you can use #MockBean to mock its implementation in the test. This way, wherever a bean of type MyInterfaceA is used, the mock will be injected in its place, and you can have the mock do whatever you want.

Spring - Combination of JDK interfaces and CGLIB proxies

We recently migrated from a pretty old Spring version (3.2.16.RELEASE) to one of the latest (4.2.5.RELEASE). Because of this change we were able to remove in some .xml files more than 1k lines of code and replace them with just about 50-100 annotations in the Java classes. All in all a great change.
Yesterday I also started the process of removing all interfaces that were being added by the #Service-annotation. So, before we had something like this:
//The interface:
public interface SomeInterfaceService extends DtoProcessingService<SimpleDto> {
}
//The class:
#Service("someClassService")
public class SomeClassService
extends SomeAbstractClassService<SimpleDto, Strategy>
implements SomeInterfaceService {
...
}
Which we've refactored to:
// The interface has been removed
//The class:
#Service
public class SomeClassService
extends SomeAbstractClassService<SimpleDto, Stategy> {
...
}
In the new Spring versions, #Service automatically uses the class-name starting with a lowercase (so someClassService).
At first we received some errors, and a possible solution for this was a Spring xml-setting to explicitly use proxy classes. So, I've read a bit about what the force of these proxies imply, and found the following things:
... According to the project page "CGLIB is used to extend Java classes and implements interfaces at runtime". So in this case the trick consists on create a proxy that EXTENDS the original object and therefore can be used instead. (source)
1) final methods cannot be advised, as they cannot be overriden. (source)
2) You will need the CGLIB 2 binaries on your classpath, whereas dynamic proxies are available with the JDK. Spring will automatically warn you when it needs CGLIB and the CGLIB library classes are not found on the classpath. (source)
3) The constructor of your proxied object will be called twice. This is a natural consequence of the CGLIB proxy model whereby a subclass is generated for each proxied object. For each proxied instance, two objects are created: the actual proxied object and an instance of the subclass that implements the advice. This behavior is not exhibited when using JDK proxies. Usually, calling the constructor of the proxied type twice, is not an issue, as there are usually only assignments taking place and no real logic is implemented in the constructor. (source)
4) Your classes cannot be final. (source 1 & source 2)
None of our classes were final, none of their methods were final, none of the classes had implicit Constructors, so I've added this setting to the Spring xml:
<tx:annotation-driven proxy-target-class="true"/>
And the error disappeared.
Now I have a few problems and concerns though:
Some classes / interfaces were a bit too difficult to refactor, so we left them as they were (for now). These are mostly class-trees with a lot of generics, abstraction and therefore difficult to refactor easily. Also, there are some other classes with interfaces I haven't even touched yet that still use interfaces.
Is this possible with the setting above, to use both CGLIB proxies AND JDK interfaces?
My guess is not entirely. Why? The classes with interfaces still seem to be initialized, but the fields that used to be filled automatically with Spring / Tapestry, aren't anymore for these classes (and I'm getting NullPointerExceptions everywhere). For example, the following used to work fine before the changes, but geometryMessageService is now null:
// Note that this is an unchanged class
#Transactional
#Service("geometryService")
public class DefaultGeometryService implements GeometryService {
...
private GeometryMessageService geometryMessageService;
public void setGeometryBerichtService(final GeometryBerichtService geometryBerichtService) {
this.geometryBerichtService = geometryBerichtService;
}
public void someMethod(){
...
this.geometryBerichtService.doSomething(); // <- NullPointerException
...
}
}

Package access level to class

What is the access scope of a class when defined with no access specifier?
For example:
package com.foo.bar;
class MyFoo{
// All Class definition
}
I know that such class is called package class as oppose to public class. So my question is from where can we access and use such class (as they seems to be accessible from no where). Can I access it from another public class of same package?
For example:
package com.foo.bar;
public class MyBar{
MyFoo foo; // Compiler throwing and error at this line
// Rest of definition
}
I have asked google but couldn't got a response from there.
It means that class is available for elements of same package.
You can absolutely access it by import statement as you can't access it from anywhere directly (means without importing) like you can do that with public class.You have to add import statement.
import pack1.pack2.MyClass;
Your first class is package-private which means it's visible to other classes in the same package, so all in all your example should compile. Here's the canonical tutorial link on Java access rules.
It should not be necessary to import ... when classes are in the same package!
What's the error?
Cheers,
From The Java™ Tutorials Controlling Access to Members of a Class
… If a class has no modifier
(the default, also known as package-private), it is visible only
within its own package (packages are named groups of related classes —
you will learn about them in a later lesson.)
It is often crucial to limit (if not avoid) the use of concrete classes by client classes and rather rely on interfaces.
Indeed such dependencies on concrete classes make client code fragile with respect to the introduction of new concrete classes of the same kind (implementing the same interface).
The client classes will only declare variables or collections or methods typed with the interface and thus rely on polymorphic methods.
Then concrete classes can be package-private (but see the point on instanciation below) since the client classes only need the interface(s) that will typically be public.
The advantage of declaring a set of package-private concrete classes is that it helps preventing the introduction of careless dependencies to them.
One issue however is about creating instances of the concrete classes since the new operator is not polymorphic.
One thus needs to rely on sophisticated methods (dependency injection, creational patterns such as Prototype or some factory, involved tools such as Spring or Guice ...). Even then, package-level visibility can be too restrictive to apply those instanciation methods conveniently.

Can someone explain what com.google.inject does?

I've seen a class declared with its only constructor being annotated with #Inject.
And I don't see the one constructor being called anywhere in the entire project.
So two questions:
<1> What does #Inject mean? (What does it do? Why is the constructor being annotated with it?)
<2> As mentioned, the constructor never gets called directly, does that have anything to do with the fact that it is annotated with #Inject?
Google Guice is a dependency injection library that allows you to construct objects simply by declaring relationships between them. Objects are constructed as they are demanded to construct other objects. You can also implement abstract classes or interfaces with different implementations by configuring Guice, which makes it very useful for running or testing your code.
#Inject annotates constructors and methods that determine what an object needs to be initialized. There are also a lot of other annotations that determine how Guice works. But simply annotating objects isn't enough; you also have to configure them with Guice bindings.
Here's a really simple example (from one of my applications). I have a MySQLDataTracker that requires a MysqlConnectionPoolDataSource:
public class MySQLDataTracker extends ExperimentDataTracker {
#Inject
public MySQLDataTracker(MysqlConnectionPoolDataSource ds) {
....
}
}
Note that MySQLDataTracker extends ExperimentDataTracker, an abstract class that can be implemented several ways. In my Guice bindings I declare that
bind(ExperimentDataTracker.class).to(MySQLDataTracker.class);
This declares that whenever I want an ExperimentDataTracker, a MySQLDataTracker will be constructed. I also need to make sure that the requisite object for constructing this is available, so I declare a provider:
#Provides #Singleton
MysqlConnectionPoolDataSource getMysqlCPDS() {
return (some thingy I construct...);
}
This says that there should only be a single connection pool data source. It also means that when I try to get an instance of ExperimentDataTracker, Guice has everything it needs to construct it. If I didn't have the above, it would throw an error.
ExperimentDataTracker tracker = injector.getInstance(ExperimentDataTracker.class);
However, it doesn't stop here. Other things depend on the ExperimentDataTracker, so it's used in turn to inject other objects. At the top level of my code there is actually only one call to getInstance, which makes Guice construct pretty much everything. I don't have to write the new statement anywhere.
I'm a big fan of Guice after seeing how it reduced the need for me to initialize a bunch of objects in order to initialize other objects. Basically I just ask for the object I want, and poof! it appears.

Java interface static method workaround?

We have a given REST interface:
POST /calculation
<data>abc</data>
This calculation can be implemented by different logical "calculators" depending on the server config.
We are now designing the Java interface that each calculator must implement. The interface will have a method for each REST service.
Given that all REST (and HTTP) calls are stateless, each method should be static. However you can't define static methods in Java interfaces. Is there a good workaround for this situation?
We could define the methods as non static and then just first create an instance of the calculator class. It just seems cleaner to indicate that the methods are stateless by using the static keyword in the interface.
Stateless doesn't mean static. Stateless means that the component doesn't rely on state. I say component, because the whole implementation of your interface is actually stateless - it will not have any member variables. So multiple instances of the implementation classes are perfectly OK. Especially if you have a context to manage them - Spring or EJB for example.
It seems to me that you want an interface with the methods declared as normal, and an implementing class, and then simply instantiate a single instance of this. There's no reason per se for the methods themselves to be static.
Why do you think the methods should be static? They surely could be, but that would limit you in terms of plugging in a different implementation later. If you are concerned about memory consumption or the like, using a Singleton would do the same as static for you, as you already said in the last paragraph of your question.
If none of classes implementing this interface does not need to change the implementation, use static method in interface as helper method.
You won't need any workaround with java 8 version.
Java 8 supports static methods in interface. Have a look at this documentation page.
Static Methods:
In addition to default methods, you can define static methods in interfaces. (A static method is a method that is associated with the class in which it is defined rather than with any object. Every instance of the class shares its static methods.)
This makes it easier for you to organize helper methods in your libraries; you can keep static methods specific to an interface in the same interface rather than in a separate class
Other solution to your problem is using Singleton as suggested in accepted answer.

Categories

Resources