I'd like to have some init params in my web.xml and retrieve them later in the application, I know I can do this when I have a normal servlet. However with resteasy I configure HttpServletDispatcher to be my default servlet so I'm not quite sure how I can access this from my rest resource. This might be completely simple or I might need to use a different approach, either way it would be good to know what you guys think. Following is my web.xml,
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>RestEasy sample Web Application</display-name>
<!-- <context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param> -->
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.pravin.sample.YoWorldApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
My question is how do I set something in the init-param and then retrieve it later in a restful resource. Any hints would be appreciated. Thanks guys!
Use the #Context annotation to inject whatever you want into your method:
#GET
public Response getWhatever(#Context ServletContext servletContext) {
String myParm = servletContext.getInitParameter("parmName");
}
With #Context you can inject HttpHeaders, UriInfo, Request, HttpServletRequest, HttpServletResponse, ServletConvig, ServletContext, SecurityContext.
Or anything else if you use this code:
public class MyApplication extends Application {
public MyApplication(#Context Dispatcher dispatcher) {
MyClass myInstance = new MyClass();
dispatcher.getDefautlContextObjects().
put(MyClass.class, myInstance);
}
}
#GET
public Response getWhatever(#Context MyClass myInstance) {
myInstance.doWhatever();
}
Related
I'm using Spring Integration's (version 4.3.1) int-http:inbound-gateway and I'm find #pathVariables aren't getting set.
<int-http:inbound-gateway id="httpInboundGatewayPathAdapterControlBus"
request-channel="controlBusIn"
reply-channel="controlBusWithReplyChannel"
supported-methods="GET"
path="{pathvalue}" request-payload-type="java.lang.String"
payload-expression="#pathVariables.pathvalue">
My web.xml
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<servlet>
<servlet-name>httpInboundGatewayPathAdapterControlBus</servlet-name>
<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>httpInboundGatewayPathAdapterControlBus</servlet-name>
<url-pattern>/controlBusURIExpression/*</url-pattern>
</servlet-mapping>
Debugging seems to show that spring's HttpRequestHandlingEndpointSupport finds nothing set URI_TEMPLATE_VARIABLES_ATTRIBUTE below :-
Map<String, String> pathVariables =
(Map<String, String>) servletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
I also tried adding
<bean id="integrationRequestMappingHandlerMapping" class="org.springframework.integration.http.inbound.IntegrationRequestMappingHandlerMapping"/>
But still get an Exception, I think because no path variables are being added in, and the stacktrace indicates that IntegrationRequestMappingHandlerMapping isn't being used.
Any help would be much appreciated.
2017-02-17 11:26:03.223:WARN:oejs.ServletHandler:qtp2505735-16: /xxxxxxxxx-integration-app/controlBusURIExpression/controlBus/getCreateCheckCaseCurrentConsumers
org.springframework.expression.spel.SpelEvaluationException: EL1007E:(pos 0): Property or field 'pathvalue' cannot be found on null
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:220)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:94)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:46)
at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:374)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:120)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:242)
at org.springframework.integration.http.inbound.HttpRequestHandlingEndpointSupport.actualDoHandleRequest(HttpRequestHandlingEndpointSupport.java:463)
at org.springframework.integration.http.inbound.HttpRequestHandlingEndpointSupport.doHandleRequest(HttpRequestHandlingEndpointSupport.java:399)
at org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway.handleRequest(HttpRequestHandlingMessagingGateway.java:103)
at org.springframework.web.context.support.HttpRequestHandlerServlet.service(HttpRequestHandlerServlet.java:67)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:806)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669)
I just tried it with the http sample app, changing the inbound gateway to
<int-http:inbound-gateway request-channel="receiveChannel"
path="{pathValue}"
payload-expression="#pathVariables.pathValue"
supported-methods="GET"/>
And it worked fine for me:
I can only get that error by mis-typing the variable name.
Your web.xml should be something like this...
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>http</display-name>
<servlet>
<servlet-name>SI</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/servlet-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SI</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
My config is a bean that I inject in my code wherever I need it. However, when injected, I get a new instance of the bean instead of the one from the session.
My bean:
#Named
#SessionScoped
public class TestModel implements Serializable {
private static final long serialVersionUID = 4873651498076344849L;
private String version;
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public void changeVersion() {
this.version = "Version 2";
System.out.println("New version : " + version + ", Object : " + this);
}
}
When injected in different classes, all occurences are different instances.
When annotating the bean with #ApplicationScoped, it is the same instance.
I do need the bean to be #SessionScoped since every user should have his own config.
The WebApp is running on TomEE 1.7.4
UPDATE: I created a new project to test it, and the SessionScope works. I now need to find out what is wrong with my current project in order to fix it.
Facets:
CDI 1.0
Dynamic Web Module 3.0
Java 1.8
JSF 2.2 (MyFaces impl from TomEE)
JPA 2.1
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>Project</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>omega</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>
faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
</faces-config>
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="annotated">
</beans>
Any ideas ?
Looks like your test doesn't work:
testModel object = model.TestModel#689a6064
New version : Version 2, Object : model.TestModel#61606aa6
So you update an instance which is not the same as the one linked to the session (another request not reusing the same session I'd say)
You are doing it right. That is, from CDI perspective, you made no mistake and what you want is perfectly legit and should work (assuming you solved the problem of multiple sessions, which you did).
I just tried this with my own piece of code and it works as expected. You can check it on GitHub. The sample is more or less identical to yours.
However, I am running Wildfly 10 and therefore Weld 2.3 which comes with it (Weld being a reference impl of CDI). While you are running TomEE which contains OpenWebBeans (another CDI implementation).
To me it seems like you either missed some TomEE/OWB specific configuration (unrealistic scenario) or, more likely, you found a bug. In any case, if I were you, I would try asking on their forums or creating an issue in their tracking system because, once again, there is imho nothing wrong with your bean/servlet setup.
We have #SessionScope annotation in both JSF & CDI. Please review whether the annotation you are using in your old project is from JSF or from CDI.
Find more on the difference between the annotation from JSF & CDI
We are using Tomcat 7.0.54.
The web.xml:
<context-param>
<param-name>log4jContextName</param-name>
<param-value>SabaLog4jContext</param-value>
</context-param>
There is sample servlet which starts on load
<servlet>
<servlet-name>startUp</servlet-name>
<servlet-class>foo.StartupServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
The StartupServlet simple as:
public class StartupServlet extends HttpServlet {
#Override
public void init() throws ServletException {
getServletContext().setAttribute("test", "ATest");
super.init();
}
}
The log4j2 can not access the test attribute with ${web:attr.test} and I got the warning as:
INFO: org.apache.logging.log4j.web.WebLookup unable to resolve key 'test'
It seems that Log4j2 works fine but the problem is that it starts before my Startup. I tried to use a servletContextListener class but no luck.
I also tried to disable Log4jAutoInitialization in web.xml and manually start set them as below.
<listener>
<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>
<filter>
<filter-name>log4jServletFilter</filter-name>
<filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>log4jServletFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
But no luck:(
The log4j2.xml is as below:
<property name="baseFolder">${web:rootDir}/../logs/${web:test}</property>
So how can setup my web.xml so that my code execute before Log4j context.
The web.xml also contains spring Listeners as:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
First, make sure Tomcat is configured to provide the functionality of a servlet 3.0 container in your web.xml file:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
You'll want the 3.0 functionality so you can specify the order in which the servlets are loaded. Then you'll want to have your own ServletContainerInitializer to initialize the ServletContext attributes. Here's an snippet of one of mine:
/* Initializer that is configured, via web.xml, to initialize before Log4j2's initializer. This gives us the
* opportunity to set some servlet context attributes that Log4j2 will use when it eventually initializes.
*/
public class BitColdHardCashContainerInitializer implements ServletContainerInitializer {
#Override
public void onStartup(final Set<Class<?>> classes, final ServletContext servletContext) throws ServletException {
if (servletContext.getMajorVersion() > 2) {
servletContext.log("BitColdHardCashContainerInitializer starting up in Servlet 3.0+ environment.");
}
// Set the webapp.name attribute so that Log4j2 may use it to create a path for log files.
servletContext.setAttribute("webapp.name", servletContext.getContextPath().replaceAll("/", "").trim());
Next, you want your ServerContainerInitializer to run before Log4j2's. In your web.xml, give your servlet a name:
<absolute-ordering>
<name>BitColdHardCash</name>
<others/>
</absolute-ordering>
This needs to be be specified before the <servlet> element.
Create a web-fragment.xml file:
<web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
version="3.0" metadata-complete="true">
<name>BitColdHardCash</name>
<distributable />
<ordering>
<before>
<others />
</before>
</ordering>
</web-fragment>
This tells Tomcat to initialize your ServletContainerInitializer first, before anything else, including Log4j2's. This goes in the META-INF directory.
That should do it. One more thing to check would be your catalina.properties file. You are using a version of Tomcat that fixes a bug regarding the calling of ServletContextInitializers. I'm not sure if the bug was in Tomcat source code or in the default supplied catalina.properties file. In the event you are using a catalina.properties file that pre-dates the fix, just crack it open an ensure that log4j*.jar is not included in the list of files specified for the tomcat.util.scan.DefaultJarScanner.jarsToSkip property.
In case I want to read bean definitions from spring-application-context.xml, I would do this in web.xml file.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
In case I want to read bean definitions through Java Configuration Class (AnnotationConfigWebApplicationContext), I would do this in web.xml
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
org.package.MyConfigAnnotatedClass
</param-value>
</init-param>
</servlet>
How do I use both in my application. like reading beans from both configuration xml file and annotated class.
Is there a way to load spring beans in xml file while we are using AppConfigAnnotatedClass to instantiate/use rest of the beans.
This didnt work
Xml file defines bean as
<bean name="mybean" class="org.somepackage.MyBean"/>
Java Class Imports Resources as
#ImportResource(value = {"classpath:some-other-context.xml"})
#Configuration
public class MyConfigAnnotatedClass {
#Inject
MyBean mybean;
}
But mybean value is always null which ofcourse will give nullpointerexception when calling method on mybean.
You can annotate your #Configuration class with
#ImportResource(value = {"classpath:some-other-context.xml"})
#Configuration
public class MyConfigAnnotatedClass {
...
}
to have it import <beans> type xml contexts.
You can do the same thing the other way around. Your #Configuration class is also a #Component. If you have a <component-scan> that includes its package, all its declared beans will be added to the context. Alternatively, you can do
<bean name="myAdditionalConfig" class="org.somepackage.MyConfigAnnotatedClass" />
Note that package cannot be used as a name in the package structure.
I am using Spring 3 and implementing Uploadify. The problem is, the files are updating properly but it is giving HTTP Error 404, on completion of file upload. I tried every possible solution, but none of them works.
The files are uploaded. Values are storing in DB properly, only that i am getting HTTP Error 404. Any help is appreciated and Thanks in advance.
The Solution is :
Finally i found the solution but it is lame.
I removed the return "" and changed the method as void. Thats it.
But still i don't understand why the same code is working in Spring 2.5.6 and not in 3.
The URL of the screenshot : http://imgur.com/bf3qo
The JSP Page
$(function() {
$('#file_upload').uploadify({
'swf' : 'scripts/uploadify.swf',
'fileObjName' : 'the_file',
'fileTypeExts' : '*.gif; *.jpg; *.jpeg; *.png',
'multi' : true,
'uploader' : '/photo/savePhoto',
'fileSizeLimit' : '10MB',
'uploadLimit' : 50,
'onUploadStart' : function(file) {
$('#file_upload').uploadify('settings', 'formData', {'trip_id' :'1', 'trip_name' :'Sample Trip', 'destination_trip' :'Mumbai','user_id' :'1','email' :'s#s.com','city_id' :'12'});
},
'onQueueComplete' : function(queueData) {
console.log('queueData : '+queueData);
window.location.href = "trip/details/1";
}
});
});
The Controller
#RequestMapping(value="photo/{action}", method=RequestMethod.POST)
public String postHandler(#PathVariable("action") String action, HttpServletRequest request) {
if(action.equals("savePhoto"))
{
try{
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request;
MultipartFile file = multipartRequest.getFile("the_file");
String trip_id = request.getParameter("trip_id");
String trip_name = request.getParameter("trip_name");
String destination_trip = request.getParameter("destination_trip");
String user_id = request.getParameter("user_id");
String email = request.getParameter("email");
String city_id = request.getParameter("city_id");
photo.savePhoto(file,trip_id,trip_name,destination_trip,user_id,email,city_id);
photo.updatetrip(photo_id,trip_id);
}catch(Exception e ){e.printStackTrace();}
}
return "";
} **Solution** : Change the method return type as void and remove the return
spring config
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
<property name="maxUploadSize" value="10000000"/>
</bean>
Web.xml is
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>project_name</display-name>
<distributable/>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/project_name-servlet.xml,/WEB-INF/applicationContext-jdbc.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>project_name</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>project_name</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
maybe you simply haven't page trip/details/1 in your application?
EDIT:
Change window.location.href = "trip/details/1"; to
window.location.href = "<%= request.getContextPath() %>/trip/details/1";
The files are uploaded. Values are storing in DB properly, only that i
am getting HTTP Error 404.
What this tells me is that your request is properly being submitted to the URL at '/photo/*'
and is properly handled by the postHandler() method.
You're getting a 404 because your web application doesn't know what to do with the url of "" that the postHandler() method is trying to direct you to.
There is most likely (and I'm making some assumptions here, it'd be helpful if you included the web.xml) a request mapper not set up to handle the " " that your controller is returning; make your controller return some sort of meaningful view name that has a valid servlet mapping and you will not get a 404.
I had this problem too. I added "#ResponseBody" and got the right result.
I think the problem is that without the annotation "#ResponseBody", the returned string is handled by some strange resolver and javascript code gets response of unexpected form.
#RequestMapping(value="/uploadFile",method=RequestMethod.POST)
public #ResponseBody String upload(HttpServletResponse response,
HttpServletRequest request) throws IOException{