So I have done research of the different layers of a spring application and so far for my first spring application I think I have done quite a good job. I am confused of where to put a FileController class. It might not even be a controller at all but more a service, i'm not sure. Maybe this is just a bad idea and I should just really use something like Spring batch. I just don't think I have the need for that type of scalability. I think the most complicated thing I might do is read and write an excel file of 5,000 lines max. The file controller below I would extend to read and write both text and .xls files. Should this be a controller and stay in the controller directory of a spring mvc web application or should this be a service and within the service directory or should this be a bean and some other directory? The file controller will only ever be accessed by a service object which will be called by a Spring MVC controller through a post or get request. I think my inexperience is really shining here.
Basically which annotation should I use: #Controller, #Bean, #Service?
I read that the #Controller annotation is primarily only used for request mappings. But it would make sense to have controllers that weren't web based.
Should I just use Spring Batch?
class example
public class FileController {
List<String> readFile(String filename) { //some impl }
String readFile(String filename) { //some impl }
void writeFile(List<String> content) { //some impl }
void writeFile(String content) { //some impl }
void close() { //some imple }
}
I also thought about just adding the reading and writing to a file within the method that it is used but I thought this was a bad approach since I have the possibility of needed the same logic in the future, DRY.
#Controller annotation is used for beans that map methods onto URI and HTTP mehtod. Such beans sits on top of web layer typically.
As your bean is not going to be accessed from web, is can't be #Controller. From my opinion it is a service. So just rename it to FileService and annotate it with #Service.
Related
A Play project (Scala or Java, I use Scala here) created with activator starts with examples like:
class MyController #Inject() {...}
There are several such components that one can inject by default, e.g. Environment, and one of them is Database:
class MyController #Inject()(db: Database) {...}
It manages to read my conf and create a corresponding Database object that I can use in this controller - which I am unable to do otherwise without copying the db configuration.
But is it the right place to do so? Most of the controller will not use the database, so why not use a kind of "SqlHandler" that does all the database-related stuff. I though of something like
#Singleton
class SqlHandler #Inject()(db: Database) {
def select() = {...db...}
def insert() = {...db...}
}
and then call it like
class MyController #Inject() {
def mySqlAction = Action {
SqlHandler.select()
}
}
Is it a good idea? Should I even use injection? And how do I use this singleton in the rest of my app then? (at the moment my SqlHandler is an object since its methods are static).
Yes, It's good practice to place domain logic in other Module like Service, SqlHandler not in controller.
I place custom action with authenticate and filter, error handling and manipulating result code in Controller
You can inject SqlHanlder to Controller.
class MyController #Inject()(handler: SqlHandler)
I have this scenario where i have my EJB3 beans in a jar file, deployed successfully to Jboss EAP-6.4.
Then I have another web project that looks up these EJB's inside a REST POJO class. I can currently access the EJB's from inside the web project using #Inject and #EJB, but my use case is one that i don't know which beans i need to load until runtime and the list is not static, so i might need to lookup 10 EJB's or none for a particular request etc.
I know I can possibly use
InitialContext.lookup('ejb:/.....')
to retrieve my EJB beans from inside the web project, but is there a way that i can retrieve them without that round trip(i believe), or maybe what am just looking for is a more elegant way to do EJB look-up at runtime just like the statically typed #EJB and #Inject versions.
Any suggestions are greatly appreciated.
EDIT
In my REST POJO classes i don't want to hard code any #Inject or #EJB annotations, rather i want that when a request comes in i look-up(for lack of better word) the EJB's that will handle the request, so all the decision is made at runtime really, as shown below
#Path("/path")
public class TestService {
#GET("/{id}")
public String loadGetPath(#Param id int id){
//at this point i want to dynamically resolve the EJB based on
//the value of id
}
}
Whoopdicity blog: Developing a dynamic JEE service client with CDI seems to have what you are looking for. At the end it claims you can do:
public class MyServiceConsumer {
#Inject #ServiceClient
private MyBusinessService service;
...
}
Instead of
public class MyServiceConsumer {
#EJB(lookup="...")
private MyBusinessService service;
...
}
To use jamon in spring, it's described to use JamonPerformanceMonitorInterceptor and put it to springs AOP-mechanism via a applicationContext.xml. It's explained, and there's an example within the tests in it's sources. Unfortunately, I want to build a spring-boot application without any xml-configuration.
Is it possible to use some annotations to include the JamonPerformanceMonitorInterceptor to spring?
Better late than never...
I had the very same situation: I needed to configure JAMon without any XML configuration. Most of the examples online (including the comments in the JAMon source code) advertise XML configuration flexibility, but I couldn't find any examples with annotation based configuration. Also annotation-based configs are not necessarily less flexible, they just need to be conceptually separated and not confused with functional parts of the application. I think such advisor can be a good example:
#Component
public class MonitoringAdvisor extends AbstractPointcutAdvisor {
private final StaticMethodMatcherPointcut pointcut = new StaticMethodMatcherPointcut() {
#Override
public boolean matches(Method method, Class<?> targetClass) {
return targetClass.isAnnotationPresent(RestController.class);
}
};
#Override
public Pointcut getPointcut() {
return this.pointcut;
}
#Override
public Advice getAdvice() {
return new JamonPerformanceMonitorInterceptor(true, true);
}
}
This advisor would let Spring/AOP know to run JAMon monitoring advice on any method of Spring bean annotated with #RestContrller. This advisor should be configured/added to the same Spring context as rest controllers.
Note, that in my case I specifically wanted to monitor my rest controllers. One can adapt the advisor according to his/her own needs. (In my code I use a more advanced/configurable version of the presented advisor)
Is this Spring Boot sample application helpful?
Here is the relevant part of the Spring AOP manual.
I have a spring service that provides configuration data. When the service is invoked by the GUI, it loads the configuration data from the database. It turns out that this happens quite often during the rendering of a single request. I want to optimize this by caching the configuration data. However, I am not sure if this is a good programming style or if it is "allowed" to have an instance variable in a service.
Here is some example code of what I am thinking of doing:
#Serivce("MyConfigService")
public class MyConfigServiceImpl implements MyConfigService {
private Config cachedConfig;
#Override
public Config loadConfig() {
if (cachedConfig != null) {
// load config
cachedConfig = loadedConfig;
}
return cachedConfig;
}
#Override
public saveConfig(Config config) {
cachedConfig = null;
// save the configuration
}
}
Having a instance variable (not managed by spring) introduces the possibility of the service becoming thread unsafe. So I try to avoid them, or make sure they are thread safe.
You may want to look at #configurable and #postconstuct annotations to achieve your goals.
Are instance variables allowed in Spring service layer classes? Sure.
Is it a good idea to use one to save a reference to the Config object here?
Maybe, maybe not.
You're not showing how Config normally gets loaded... Does the same Config instance get returned to all users? i.e. - When User1 calls saveConfig then User2 calls loadConfig User2 gets the Config object User1 saved.
If so, you should be able to cache the value with no problems.
Also, instead of implementing it yourself, you could use Spring's annotation-based caching.
Instance variables is what Spring IoC container is all about; what is dubious in your design is that you have your own lazy-loading logic in loadConfig—that's the concern you must leave to Spring via lazy-init=true (or similar, I don't remember exactly). The design will also probably involve lookup methods and posibly request-scoped beans.
I am having bean AddressBean, which has some properties like addressLine1, city etc.
Before persisting it to DB using AddressBeanService, I am prevalidating it, and after saving, i am post validating it, using preValidate and postValidate function in ValidateAddressService. And all this i am triggering from a AddressBeanHelper class.
class AddressBeanHelper{
AddressBean bean =null;
AddressBeanHelper(AddressBean bean){
this.bean=bean;
}
ValidationService validate=new ValidateAddressService();
function doStuff(){
validate.preValidateAddressBean (bean);
//business logic for AddressBean
validate.preValidateAddressBean (bean);
}
}
class ValidateAddressService implements ValidationService <AddressBean>{
preValidateAddressBean (AddressBean bean){
//here is the issue
}
preValidateAddressBean (AddressBean bean){
//here is the issue
}
}
I want some framework or trick in spring by which i just need to write generic code in validation functions and externalize my validation rule outside the code itself.
Like a rule engine which can automatically validates each and every property of bean.
currently my application infrastructure is spring/hibernate for server side, jsp/jquery on client side and deployment server is on heroku.
Have a look at this one:
http://hillert.blogspot.com/2011/12/method-validation-with-hibernate.html
It supports JSR-303, so its a standard. Its very easy to implement, and it supports, custom and some predefined ready to use validators.
You can also find some references here:
http://java.dzone.com/articles/method-validation-spring-31