spring dynamic views of different directories - java

this is my first post in stackoverflow and also i'm new to spring. this is my question(please don't mind my language)
this is my folder structure of the project in netbeans(i cant post images yet because i have no 10 reputations)
WEB-INF
views
sales
sales_invoice.jsp
sales_order.jsp
sales_order_list.jsp
sales_invoice_list.jsp
purchase
purchase_order.jsp
grn.jsp
accounts
account_list.jsp
web.xml
spring-dispatcher-servlet.xml
I want to invoke jsps inside any directory under view folder using spring i try to do in this way but i was unable to do that under my knowledge. (In the web xml i use InternalViewResolver and also i used annotation to define controllers and requestMappings)
please tell me how to invoke thease jsp using this way or another way because my final project is waiting till your possible responses
Thank You

Here i am assuming that you have created mvc-dispatch-servlate.xml in which you have configuration like this.
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
your controller code should be like this if want to access sales > sales_invoice.jsp
#Controller
#RequestMapping("/sales")
public class SalesController{
#RequestMapping(value="/sales-invoice", method = RequestMethod.GET)
public String salesInvoice(ModelMap model) {
model.addAttribute("message", "Hello Spring MVC Framework!");
return "sales/sales_invoice";
}
}

Related

How to give the view page in Spring controller if they are in different folders?

I am having two folders in my WEB-INF.
Folder1 contains 3 jsp like page1.jsp , page2.jsp , page3.jsp .
Folder2 contains the page4.jsp.
In dispatcher-Serlet.xml I have configured like ,
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/folder1/" />
<property name="suffix" value=".jsp" />
</bean>
In Controller ,
#RequestMapping(value="page4.html",method=RequestMethod.GET)
public String getTransfer(){
List<String> list = new LinkedList<String>();
Hashtable<String , Object> map = MyHashtableClasss.getDetails;
if(!map.isEmpty()){
Set<String> keys = map.keySet();
for(String key: keys){
list.add(map.get(key).getUserName());
}
}
model.addAttribute(list);
return "page4";
}
How can I get page4.jsp in to the view . Because I didn't have that page4.jsp in Folder1.
In general , How can show the different JSP's in differenf folders in Spring.Is that possible ? If not , what is the alternative.
Hope our stack user will help me.
1 Change
<property name="prefix" value="/WEB-INF/folder1/" />
to
<property name="prefix" value="/WEB-INF/" />
and return view with folder path
return "folder1/page4";
2 Other way is to configure multiple view resolver beans and set the priority for each. Check following links for solution and limitations.
Multiple View resolvers in spring mvc
Spring MVC with multiple view resolvers
EDIT
The other way is to build your own view resolver by extending InternalResourceViewResolver. In extended view resolver you can add logic to scan sub folders and find the jsp file with the returned view name.
It's your choice what folder to specify for the ViewResolver.
If you specify /folder1, the JSPs will be resolved under folder1. If you don't, you'll need to specify /folder1 yourself when you want it.
You can use a function, or a constant, to do that for you if you really need to or it helps factoring..
public class Views {
public static String legacy (String name) {return "folder1/"+name;}
public static String modern (String name) {return "folder2/"+name;}
}
If you define Controllers in a separate application-context, you can hook them up with a separately-configured ViewResolver (with a different path).
But all this seems pretty obvious to me, I'm not really sure why you're asking such a question. Can Spring magically know that for one view, you want a different folder? I hope not, I'd prefer it to just work reliably in the folder that I specify.

Sending data from client to server in Spring

I am developing a web application using spring MVC, Hiberbate and MySQL database. I am trying to send data to server from a client, but I can not do it.
In detail,
I want to send my JSON data to http://localhost:8080/app/test . In my test controller I want to get the data which comes from the client and write it to screen or save it to db. I have been searching about 3 days and I have tried many strategies to do it, but I can not.
You must explicitly tell spring to use a json parser.
For instance, here is a piece of my DispatcherServlet config :
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonConverter" />
</list>
</property>
</bean>
<bean id="jsonConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
Jackson Must be in your classpath.
Then you write a method like this one in your annotated controller :
#RequestMapping(value = "/test", method = RequestMethod.POST)
public void myMethod(#RequestBody MyObject object) {
//... do what you want with the object
}
You just have to send an JSON object with properties that match the ones in MyObject, via a POST request.

Spring MappingJacksonJsonView, how to tell to use it instead of JSP view?

I'm trying to use MappingJacksonJsonView with Spring 3.0, without success. I don't know what I'm doing wrong, I think the problem is that I don't know how to tell to use the MappingJacksonJsonView to render a request. I tried to use the same name for view name and bean name of MappingJacksonView, but didn't work. I built a sample test application here: https://github.com/stivlo/restjson
In web.xml I've defined ContextLoaderListener and the mapping for dispatcherServlet.
In servlet-context.xml I've added
<mvc:annotation-driven/>
and
<bean name="jsonView"
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
In org.obliquid.restjson.web.ToDoList.java I set the logical view name as jsonView.
However, instead of using MappingJacksonJsonView, it looks for a JSP file, according to my JSP mapping.
message /restjson/WEB-INF/jsp/jsonView.jsp
description The requested resource (/restjson/WEB-INF/jsp/jsonView.jsp)
is not available.
What should I change to use MappingJacksonJsonView as a renderer?
UPDATE 1: In following tests I've found that if I add the following to my servlet-context.xml, JSON rendering works, but my other view, rendered as JSP (home) is not working anymore.
<!-- Resolve views based on string names -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
UPDATE 2: I removed the BeanNameViewResolver and changed my ToDoList.java to return directly the Collection to be converted in JSON, instead of ModelAndView, with a #ResponseBody annotation, as follows:
#RequestMapping("/toDoList")
public #ResponseBody List<ToDoItem> test() {
List<ToDoItem> toDoList = new ArrayList<ToDoItem>();
toDoList.add(new ToDoItem(1, "First thing, first"));
toDoList.add(new ToDoItem(1, "After that, do the second task"));
return toDoList;
}
In this way it works. Even though the mapping is even more "magical". It makes me wonder, if a similar renderer exists for XML for instance, how does Spring know which renderer to pick?
Spring will use Accept header sent by the client to return most appropriate view. Here you will find my complete Spring MVC application that returns both JSON and XML.
As you can see, I only needed:
<mvc:annotation-driven />
I also used the same annotations: #RequestMapping to map request to a method and #ResponseBody to tell Spring that what I am returning from the controller is the actual response. It might however need some tweaking/formatting, and here Spring takes care of marshalling your object into most appropriate type like JSON.
You should do it this way:
In your xml file set the following: set
<mvc:annotation-driven />
After it you need to set Jackson serializer:
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>
after it you can use it in your Controller:
#RequestMapping(value="/getObjects",method = RequestMethod.POST)
#ResponseBody
public List<MyObject> getCategories(){
List<MyObject> objects = daoService.gettAllObjects();
return objects;
}
Adding the following worked in my case
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="0" />
</bean>
So basically we should try to resolve any view as a bean first
you will need to see ContentNegotiatingViewResolver,and set defaultviews property to MappingJacksonJsonView, and #ResponseBody uses HttpMessageConverter to instead of ViewSolver,see the differences between them
http://ufasoli.blogspot.com/2013/08/viewresolver-vs-messageconverter-spring.html

Convert SOAP to a virtual Restful service?

Is there a way to use my SOAP web service(spring-ws, java) as a XML based RESTful service virtually?
I don't want to re-write whole my SOAP web service into RESTful from scratch in java, but I need to access it through iphone using REST, which they already have easy native support.
XMLGateway, Proxys..? or some extra java code? since my SOAP request and response is simply an XML file why can't I modify it to be used by a REST service?
Or without changing changing any logic and xml parsing in my application is that easy to add jax-rs annotations and create a rest request xml?
my config spring file is like this:
<bean id="webServicePluginDescriptor"
class="com.mysite.ws.configuration.MyWebservicePluginDescriptor" />
<bean id="payloadMapping"
class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
<property name="defaultEndpoint" ref="inferenceEndPoint" />
<property name="interceptors">
<list>
<ref local="validatingInterceptor" />
<ref local="payLoadInterceptor" />
</list>
</property>
</bean>
<bean id="payLoadInterceptor"
class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor" />
<bean id="validatingInterceptor"
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schema"
value="classpath:/wsdl/Request.xsd" />
<property name="validateRequest" value="true" />
<property name="validateResponse" value="false" />
</bean>
<bean id="PropertyResource" class="com.mysite.ws.im.PropertyResource">
<property name="resource"
value="/WEB-INF/client-specific/InferenceMachine.properties" />
</bean>
<bean id="inferenceEndPoint" class="com.mysite.ws.web.InferenceEndPoint">
<property name="messageWebService" ref="messageWebService" />
</bean>
<bean id="messageWebService" class="com.mysite.ws.service.MessageWebService"
scope="request">
<aop:scoped-proxy />
<property name="inferenceService" ref="inferenceService" />
</bean>
<bean id="Request" class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="classpath:/wsdl/Request.xsd" />
</bean>
<bean id="Response" class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="classpath:/wsdl/Response.xsd" />
</bean>
<bean id="Error" class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="classpath:/wsdl/Error.xsd" />
</bean>
<bean id="mwsid"
class="org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition">
<constructor-arg value="classpath:/wsdl/mtchwsdl.wsdl" />
</bean>
<bean id="inferenceService" class="com.mysite.ws.im.InferenceService"
scope="request">
<aop:scoped-proxy />
<property name="webServiceConfiguration" ref="wsPlayerConfiguration" />
<property name="properties">
<bean class="com.mysite.ws.im.PropertyResource">
<property name="resource"
value="/WEB-INF/client-specific/InferenceMachine.properties" />
</bean>
</property>
</bean>
<!-- ~~~~~~~ Application beans ~~~~~~~ -->
<bean id="wsPlayerConfiguration"
class="com.mysite.ws.configuration.WebServiceConfiguration"
scope="request">
<aop:scoped-proxy />
<property name="playerConfiguration" ref="playerConfiguration"></property>
<property name="configurationSetup" ref="configurationSetup"></property>
</bean>
and this is my endpoint class:
/**
* The EndPoint of the Web Service Application. This class gets the raw
* SOAP-body message from the Spring Payload Dispatcher and sends the message to
* the #see MessageService class. After it has gotten the response XML message
* it returns this back to the Spring Payload Dispatcher.
*/
public class InferenceEndPoint extends AbstractJDomPayloadEndpoint {
private MessageWebService messageWebService;
public InferenceEndPoint() {
}
#Override
protected Element invokeInternal(Element inferenceRequest) throws Exception {
Element ret = messageWebService.handleRequest(inferenceRequest);
return ret;
}
/**
* #param messageWebService
*/
public void setMessageWebService(MessageWebService messageWebService) {
this.messageWebService = messageWebService;
}
}
any ideas?
Spring-WS just adds some annotations to your beans and then you have Spring beans doing most of the heavy lifting. Presumably you have some classes annotated with #Endpoint, #PayloadRoot and the like. You should be able to re-use all of these in one of three ways.
If your Spring-WS endpoint classes are adapter pattern style (e.g. your Endpoint class is injected with a POJO service that does the real work), then you could do a similar adapter-style Spring MVC Controller (where REST exists in Spring 3.0).
If you have your annotations directly on your business logic class, then in theory, you should be able to just sprinkle on some more annotations (might get a little busy-looking).
If you have Spring-WS beans that are POX (and not SOAP), then you might be able to get away with some fancy URL mappings to give them more RESTful looking URLs
To migrate to the Spring 3 for REST support, add the appropriate #RequestMapping and another annotations to expose them as REST services to match specific URLs. While you're adding, you might as well remove the old #PayloadRoots and #Endpoint, but that may not be a big deal. Of course if you leave old Spring-WS annotations around, you'll still need the Spring-WS jars on your classpath, but as long as you are not using a Spring-WS servlet nor any other other beans in your Spring file - you should be okay (in theory...).
The biggest gotchas will be:
Don't forget to remove Spring-WS beans from your Spring file
DO remember to add the Spring MVC beans to your Spring file, and most importantly different Dispatcher servlet
REST security in Spring will be provided by Spring Security, not the same SOAP interceptors found in Spring-WS, so that will be a complete overhaul. The good news is that Spring Security is actually pretty easy to work with
Looking at your code, it's very difficult to tell what the best approach would be. REST and SOAP are really quite different ways of imagining how a web-based service interface could work: SOAP is all about method calls, and REST is all about resources, representations and links. To convert, you have to start from your underlying abstract API.
If your basic API is one of “I give you a document, you give me a response document” and there's no exposure of anything other than that, it's a very SOAP-oriented model. You can model that in REST through POSTing a document and getting a response, but it's not at all elegant. If you can instead think of your interface in terms of “here's an overall resource, with properties I can set, and certain operations I can do” then that maps to REST far more easily (the overall resource is represented as a document full of links to individual property resources and operations, and the individual properties can be GET and PUT – and possibly DELETEd – as necessary). Which style you've got… well, it looks a lot like you've got the first, but I'm only guessing because determining it for real would require looking at more of your code than you've shown.
There's nothing stopping you from send POST filled with XML to get results filled with XML back.
The simplest thing to do is somehow capture the SOAP requests going back and forth, and simply turn the request in to a template with the blanks being your parameters, and then using XPath on the resulting XML to pull your results out.
The only nit being you might need SOAPAction header in your POST, but likely not.
It's really no big deal. If you have dozens of methods, it's more of a pain. Also, if you're using any of the encryption parts of SOAP, then it's more of a pain. But if just a few, in the end it's just XML, and a bulk of that XML is boilerplate, so looked at that way, it's pretty straightforward.
Addenda:
If you have back end logic that you want to front with a more HTTP friendly service, then JAX-RS can to that quite easily, but it would require coding on the server end.
If you have an existing SOAP web service that you wish to use, then forget the whole SOAP part of the equation, and simply treat it as an HTTP web service that uses XML payloads. It's still SOAP, but you're not using any SOAP tooling on the client side. You're simply assembling XML payloads on the client requests (from templates would be easiest, IMHO), and consuming XML payloads as a result, and trading these over HTTP.
Depending on how many different methods on the existing web service you intend to call gives you an idea of the scope of the work involved. It's simple work (once you can view the payloads easily), but it's still work. If you only have a few methods, especially if the interface is stable and not changing, it's far easier to just work with the raw XML than learn and fight some new unfamiliar framework.
This is how I solved that problem, using Spring Boot + Spring Integration.
Having a WSDL of the SOAP WS, I used maven-jaxb2-plugin to have my Java POJO's generated at build time.
Optionally, you could create transformations to adapt those classes and attributes to what the REST client expected.
Using Spring Integration, I mapped every REST endpoint to a SOAP gateway like this:
#Bean
public IntegrationFlow myFlow(GenericTransformer reqTransformer, GenericTransformer resTransformer) {
return IntegrationFlows
.from(this.getRestGateway(POST, "/api/entity", MyRestResponse.class))
.transform(reqTransformer)
.handle(this.getSoapGateway("gwBean"))
.enrichHeaders(h -> h.header(HttpHeaders.STATUS_CODE, HttpStatus.OK))
.transform(resTransformer)
.logAndReply();
}
private HttpRequestHandlingMessagingGateway getRestGateway(HttpMethod method, String path, Class payloadType) {
HttpRequestHandlingMessagingGateway httpGateway = new HttpRequestHandlingMessagingGateway();
RequestMapping requestMapping = new RequestMapping();
requestMapping.setMethods(method);
requestMapping.setPathPatterns(path);
httpGateway.setRequestMapping(requestMapping);
httpGateway.setReplyTimeout(timeout);
httpGateway.setRequestPayloadTypeClass(payloadType);
httpGateway.setMessageConverters(asList(jsonConverter));
return httpGateway;
}
private MarshallingWebServiceOutboundGateway getSoapGateway(String nameBean) {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath(generatedClassesPackage);
SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory();
messageFactory.setSoapVersion(SoapVersion.SOAP_12);
messageFactory.afterPropertiesSet();
MarshallingWebServiceOutboundGateway webServiceGateway = new MarshallingWebServiceOutboundGateway(soapUri, marshaller);
webServiceGateway.setMessageFactory(messageFactory);
webServiceGateway.setBeanName(nombreBean);
return webServiceGateway;
}

Import Spring config file based on property in .properties file

In my Spring xml configuration I'm trying to get something like this to work:
<beans>
<import resource="${file.to.import}" />
<!-- Other bean definitions -->
</beans>
I want to decide which file to import based on a property in a properties file.
I know that I can use a System property, but I can't add a property to the JVM at startup.
Note: The PropertyPlaceHolderConfigurer will not work. Imports are resolved before any BeanFactoryPostProcessors are run. The import element can only resolve System.properties.
Does anyone have a simple solution to this? I don't want to start subclassing framework classes and so on...
Thanks
This is, unfortunately, a lot harder than it should be. In my application I accomplished this by doing the following:
A small, "bootstrap" context that is responsible for loading a PropertyPlaceholderConfigurer bean and another bean that is responsible for bootstrapping the application context.
The 2nd bean mentioned above takes as input the "real" spring context files to load. I have my spring context files organized so that the configurable part is well known and in the same place. For example, I might have 3 config files: one.onpremise.xml, one.hosted.xml, one.multitenant.xml. The bean programmatically loads these context files into the current application context.
This works because the context files are specified as input the the bean responsible for loading them. It won't work if you just try to do an import, as you mentioned, but this has the same effect with slightly more work. The bootstrap class looks something like this:
public class Bootstrapper implements ApplicationContextAware, InitializingBean {
private WebApplicationContext context;
private String[] configLocations;
private String[] testConfigLocations;
private boolean loadTestConfigurations;
public void setConfigLocations(final String[] configLocations) {
this.configLocations = configLocations;
}
public void setTestConfigLocations(final String[] testConfigLocations) {
this.testConfigLocations = testConfigLocations;
}
public void setLoadTestConfigurations(final boolean loadTestConfigurations) {
this.loadTestConfigurations = loadTestConfigurations;
}
#Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
context = (WebApplicationContext) applicationContext;
}
#Override
public void afterPropertiesSet() throws Exception {
String[] configsToLoad = configLocations;
if (loadTestConfigurations) {
configsToLoad = new String[configLocations.length + testConfigLocations.length];
arraycopy(configLocations, 0, configsToLoad, 0, configLocations.length);
arraycopy(testConfigLocations, 0, configsToLoad, configLocations.length, testConfigLocations.length);
}
context.setConfigLocations(configsToLoad);
context.refresh();
}
}
Basically, get the application context, set its config locations, and tell it to refresh itself. This works perfectly in my application.
Hope this helps.
For the Spring 2.5 and 3.0, I have a similar solution to louis, however I've just read about 3.1's upcoming feature: property management, which sounds great too.
There is an old issue on the Spring JIRA for adding properties placeholder support for import (SPR-1358) that was resolved as "Won't Fix", but there has since been a proposed solution using an EagerPropertyPlaceholderConfigurer.
I've been lobbying to have SPR-1358 reopened, but no response so far. Perhaps if others added their use cases to the issue comments that would help raise awareness.
Why not:
read your properties file on startup
that will determine which Spring config to load
whichever Spring config is loaded sets specific stuff, then loads a common Spring config
so you're effectively inverting your current proposed solution.
Add something similar to the following:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound"><value>true</value></property>
<property name="locations">
<list>
<value>classpath:propertyfile.properties</value>
</list>
</property>
</bean>
If what you want is to specify the imported XML file name outside applicationContext.xml so that you could replace applicationContext.xml without losing the configuration of the imported XML file path, you can just add an intermediate Spring beans XML file, say, confSelector.xml, so that applicationContext.xml imports confSelector.xml and confSelector.xml only contains an <import> element that refers to the suitable custom beans XML file.
Another means that might be of use are XML entities (defined by adding <!ENTITY ... > elements into the DTD declaration at the beginning of XML). These allow importing XML fragments from other files and provide "property placeholder"-like functionality for any XML file.
Neither of these solutions allows you to have the configuration file in Java's .properties format, though.
André Schuster's answer, which I bumped, helped me solve a very similar issue I was having in wanting to find a different expression of properties depending on whether I was running on my own host, by Jenkins on our build host or in "real" deployment. I did this:
<context:property-placeholder location="file:///etc/myplace/database.properties" />
followed later by
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>WEB-INF/classes/resources/database.properties</value>
...
</list>
</property>
</bean>
which solved my problem because on my development host, I put a link to my own copy of database.properties in /etc/myplace/database.properties, and a slightly different one on the server running Jenkins. In real deployment, no such file is found, so Spring falls back on the "real" one in resources in my class files subdirectory. If the properties in question have already been specified by the file on /etc/myplace/database.properties, then (fortunately) they aren't redefined by the local file.
Another workaround which does not rely on system properties is to load the properties of all the files using a different PropertyPlaceholderConfigurer for each file and define a different placeholderPrefix for each of them.
That placeholderprefix being configured by the initial property file.
Define the first property file: (containing either first or second)
global.properties
fileToUse=first
Define the files containing a property that can be switched depending on the property defined just above:
first.properties
aProperty=propertyContentOfFirst
second.properties
aProperty=propertyContentOfSecond
Then define the place holders for all the files:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:global.properties</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="placeholderPrefix" value="first{" />
<property name="locations">
<list>
<value>classpath:first.properties</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="placeholderPrefix" value="second{" />
<property name="locations">
<list>
<value>classpath:second.properties</value>
</list>
</property>
</bean>
Use the property defined in global to identify the resource to use from the other file:
${fileToUse}{aProperty}
If I add the JVM argument below and have the file myApplicationContext.dev.xml, spring does load
-DmyEnvironment=dev
<context:property-placeholder />
<import resource="classpath:/resources/spring/myApplicationContext.${myEnvironment}.xml"/>
I'm using Spring 3 and load a properties like that:
<context:property-placeholder location="/WEB-INF/my.properties" />

Categories