I'm building a web app with custom components. I need a way to route requests to class / methods, is there any standalone java library that can achieve that (in a sexy manner [1]) ?
[1] read : no xml!
In Spring WebMVC 2.5/3 you can do it all with annotations. The obvious downside is that of course annotation values have to be compile time constant, so you can end up with some effectively hardcoded URLs. If you go all-in with autowiring, basically the only XML is a couple lines to create the servlet, turn on the autowiring + package scanning, and possibly specify the view resolution strategy.
e.g.,
#Controller
public class WebController {
#RequestMapping(value="/pages/Home.htm", method=RequestMethod.GET)
public ModelMap buildHome(#RequestParam("foo", required=false) String foo){
return fillInHomePageData(foo);
}
In a degenerate resolution strategy it could, for example, then automatically go looking for jsp/pages/Home.jsp and build it with the data you returned.
You could take a look at Reflection, it is rather sexy and does not require XML.
What it can do that it instantiates classes to route to based on input.
Related
Let's say there is an application which uses the forms package and <whatever>Form.java for validation purposes in the controller layer, so every request which needs validation has a corresponding <requestName>Form.java class.
This results in controllers methods signatures looking like this:
TemplateController.java
#PostMapping
public Mono<SmsMessageTemplate> create(#Valid #RequestBody Mono<TemplateForm> templateForm)
and then there is a service layer with method signatures looking like this:
TemplateService.java
public Mono<SmsMessageTemplate> create(TemplateForm formData) {...}
It is also possible to implement it like so:
TemplateService.java
public Mono<SmsMessageTemplate> create(String template name, String templateText) {...}
Which way is better and why? I think passing the Form classes to the service layer may be mixing of the layers concept and one should keep forms in the controller layer for a better understanding of the parameters passed without a need to navigate through classes back and forth. Do I miss something?
Such decisions trully depend on various factors f.e:
- the complexity and volume of the project (is it just a small service, or a full blown CMS / ERPS etc?)
are you going to be re-using the service in other modules/projects
are you going to distribute service interface jars ?
(then you need to think about the modules and perhaps the *Form object will not even be at the controller side - you wouldn't want to distribute your controller classes to 3rd party clients)
what about a form that contains 20 fields ? you surelly wont pass 20 arguments
what about the case of a service method that does CRUD on complex entities, say a User ? you will probably have a couple of forms / validations (register, edit) and perhaps different types of users with different options so types * actions forms. (in which case you may consider a User domain object (in a domain package) and multiple controller side form objects (you will probably need to populate a User object from/to a Form).
generally speaking, as mentioned above, it's very opinion-based but in my opinion the overall complexity and envisaged size of each project will affect your final decision.
I have been using Xml configuration for Spring Batch for a while, and feel it is simpler and concise. However, nowadays, people are suggesting to use javaconfig over xml. I googled this topic.
This site tells us why javaconfig is better https://blog.codecentric.de/en/2013/06/spring-batch-2-2-javaconfig-part-1-a-comparison-to-xml/
Top reasons to choose javaconfig over xml:
We want to do some basic configurations in the framework. People add
a dependency to our framework library and import those
configurations according to their needs. If these configurations
were written in XML, they would have a hard time opening them to
look what they are doing. No problem in Java.
There’s no navigability in XML. That may be okay as long as you
don’t have too many XML files and all of them are in your workspace,
because then you can take advantage of the Spring IDE support. But a
framework library usually should not be added as a project to the
workspace. When using Java based configuration you can perfectly
jump into framework configuration classes. I will talk more about
this subject in a following blog post.
In a framework you often have requirements
the user of the library has to fulfill in order to make everything
work, for example the need for a DataSource, a
PlatformTransactionManager and a thread pool. The implementation
doesn’t matter from the perspective of the framework, they just need
to be there. In XML you have to write some documentation for the
users of framework, telling them they need to add this and this and
this Spring bean under this name to the ApplicationContext. In Java
you just write an interface describing that contract, and people
using the library implement that interface and add it as a
configuration class to the ApplicationContext. That’s what I did
with the interface.
This site tells us why xml is better https://dzone.com/articles/consider-replacing-spring-xml
Top reasons to choose xml over javaconfig
Configuration is centralized, it’s not scattered among all different components so you can have a nice overview of beans and their wirings in a single place.
If you need to split your files, no problem, Spring let you do that. It then reassembles them at runtime through internal tags or external context files aggregation.
Only XML configuration allows for explicit wiring – as opposed to autowiring. Sometimes, the latter is a bit too magical for my own taste. Its apparent simplicity hides real complexity: not only do we need to switch between by-type and by-name autowiring, but more importantly, the strategy for choosing the relevant bean among all eligible ones escapes but the more seasoned Spring developers. Profiles seem to make this easier, but is relatively new and is known to few.
Last but not least, XML is completely orthogonal to the Java file: there’s no coupling between the 2 so that the class can be used in more than one context with different configurations.
I concluded that xmls can still be used, if you are creating standalone batch jobs and if you are not creating any new frameworks by integrating with Spring Batch.
Any disadvantage of xmls that I am missing out ?
Let me add a couple of additional thoughts on the topic.
What I really like when using javaconfig is the ability to create your jobs dynamically. E.g., you could have an inputparameter with filenames and then create a job that executes reading and processing this files in parallel by creating a step for every received filename. (using a MultiResourceItemReader would do this sequentially). Moreover, depending on inputparameter, you could also define the job flow differently.
My thoughts on your reasons why choosing xml over javaconfig:
point 1: this doesn't really count in my opinion. You can have your own configuration classes, you can define your own packages. You could even put them in own modules. This is just a matter, how you organize your code.
point 2: again, this doesn't count as well. You can split your configuration in as many classes as you'd like. You can use the #Import and #ContextScan annotation in order to integrate what you want into your context.
point 3: autowiring can also be very explicitly, if you do it by class and not by interface. Moreover, you can also call directly the method annotated with #Bean. An example:
#Configuration
public MyBeanFactory {
#Bean
public MyBeanInterface bean1() {
return ...;
}
#Bean
public MyBeanInterface bean2() {
return ...;
}
}
#Component
public MyBeanuser {
#Autowired
private MyBeanFactory beanFactory;
#PostConstruct
public void afterPropertiesSet() {
// this will actually set the bean that was created an registered in the
// spring context and not simply call the the method and create a new
// instance. So this wiring is very explicitly
setProperty1(beanFactory.bean1());
setProperty2(beanFactory.bean2());
}
In the end, I guess it is also a matter of taste. I was using xml-configuration for over 5 years in the context of spring batch. Two years ago, we completely switched to use javaconfig instead of xml. And honestly, I haven't found one single reason why I should want to go back to use xml. However, this is my "matter of taste".
Does Spring 4 keep an internal record of the mappings that are specified with #RequestParam? I am looking for a list of these mappings.
For example, if I annotate a method with:
#RequestMapping(value = "/myname", method = RequestMethod.POST)
I would want a list with myname.
I looked around a bit and I know about the Spring MVC Router project but I am simply looking for a method call that would return the mappings. Or alternatively, a list of all the paths registered with <mvc:view-controller/> would work too.
Background:
We have a business requirement to create public areas on our web application, similar to the tumblr model where you can have myname.domain.com and access an area created by that user. However, our method is using domain.com/myname since programmatically creating the former was not simple (would need to monkey with DNS/web server config files).
We extended GenericFilterBean to do this, but I want to make sure that when searching for 'myname,' the application can ignore actual pages (or more specifically, views) on the site. We want the front-end validation to disallow existing page names.
I think your question was already answered in here. This is a very good answer.
For new project, I was searching for which framework is to be used. I looked for the updates for existing frameworks.
I found it very intresting about Spring MVS controller, that in the controller itself you can now define which URL you want to hit. The best thing is that you do not need to rewrite url, that kind of feature is also there, i.e., you can give directly the url like:
\users\amit\stores\store1
Earlier I had to write url rewriting for making it this way, and actual url used to be like:
\StoreDetails?user=amit&store=store1
I found it very good. But on second thought, if I compare, if I start putting the urls in controller itself, will not it make a little difficult to maintain after say 1 year, when I have so many modifications done on the project and at times, the url given to Controller turns not related to the name of the Controller.
For example in above example, I might want to search for storedetails, but by url i would be searchin in StoreController etc.
What you guys suggest is good practice, to go with xml or to go with annotation based.
If you guys using the annotation based, do you face any issue?
Thanks & Regards
Amit
Spring MVC implements a lot of predefined conventions. For example if you do not explicitly define #RequestMapping on controller it will map it to url similar to controller name. For example if you controller is named Users it will be automatically mapped to url users. If then you rename your class to Customers it will be automatically mapped to url customers.
The same happens with methods.
The big question is whether you really want this. Typically you do not want your internal changes (including class renaming) directly and automatically affect API your provide.
If you choose to define mappings explicitly try to organize your project using certain convention that will simplify on-going support in future. You can also use public static final Strings in annotations. All URL dependent strings can be stored in one class, for example:
public interface Mapping {
public final static String USERS = "users";
public final static String PERMISSIONS = "permissions";
}
#RequestMapping(Mapping.USERS)
public UserController {
............
}
I would stick with annotations they are very simple to define and its pretty easy to discover the appropriate method from a view using a good IDE. They key is to search the entire project for a given URL string.
So for example, if I had the following jsp.
Store Link
I would just use the IDE's search feature (in Eclipse > File Search) to find /store/products/ which would most likely contain the controller in my search results. If your crafty with IDE search features the annotation mappings are really a non issue.
For a web application, I need to return a model to a view.
For a mobile application or API, I want to return xml or json.
Is it possible to do all of these using a single controller method, or do I have to duplicate this and create seperate API controller's etc?
With Spring MVC 3.x you can do this with just the one controller method. The trick is to wire up the appropriate ContentNegotiatingViewResolver in your Spring config. You can configure it to return the desired content type based on file extension and/or requested mime type.
It works best for methods that only add a single model attribute to the Model, otherwise the JSON/XML starts to get a bit ugly.
I often find its simpler/nicer to implement separate controller methods for my web service requests, as you can better control the format of the JSON/XML and the code is easier to maintain in the long term.
EDIT: Just to qualify my comment above, I find that complex JSP pages where there might be up to 5-10 model attributes added to the page, that the resulting JSON tends to be quite messy and you usually find you only really want 1-2 of those in the JSON. OTOH, simple pages with 1-2 models added work quite well.