Create custom OData v2 service with data source from S/4HANA Cloud using S/4HANA Cloud SDK: web.xml error - s4sdk

I am still trying to create a custom OData v2 service in java with an S/4HANA Cloud data source using S/4HANA Cloud SDK. Made web.xml changes as suggested in the answer to this question on March 26, but I'm getting an error in web.xml (see below) - it says init-param within servlet is invalid content.
Also, when I attempt to access service metadata through a browser with $metadata, it says 'service not found' and the Cloud Platform 'Default Trace' log has the following:
com.sap.cloud.sdk.service.prov.v2.rt.cdx.CDXRuntimeDelegate anonymous
https-jsse-nio-8041-exec-7 na masssalesorders2application web ha*******
na#na#na#na#No Runtime Providers present for the URL and
languageCFMassSalesOrdersSrv
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"
version="3.0" metadata-complete="false">
<login-config>
<auth-method>FORM</auth-method>
</login-config>
<session-config>
<session-timeout>20</session-timeout>
</session-config>
<security-role>
<role-name>Everyone</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<web-resource-name>All SAP Cloud Platform users</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>Everyone</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
<!-- Use CONFIDENTIAL as transport guarantee to ensure SSL connection (HTTPS) on public deployments
<transport-guarantee>CONFIDENTIAL</transport-guarantee> -->
</user-data-constraint>
</security-constraint>
<filter>
<filter-name>RestCsrfPreventionFilter</filter-name>
<filter-class>org.apache.catalina.filters.RestCsrfPreventionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RestCsrfPreventionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>HttpSecurityHeadersFilter</filter-name>
<filter-class>com.sap.cloud.sdk.cloudplatform.security.servlet.HttpSecurityHeadersFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HttpSecurityHeadersFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>HttpCachingHeaderFilter</filter-name>
<filter-class>com.sap.cloud.sdk.cloudplatform.security.servlet.HttpCachingHeaderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HttpCachingHeaderFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>ODataServlet</servlet-name>
<servlet-class>org.apache.olingo.odata2.core.servlet.ODataServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>org.apache.olingo.odata2.service.factory</param-name>
<param-value>
com.sap.cloud.sdk.service.prov.v2.rt.core.CloudSDKODataServiceFactory
</param-value>
</init-param>
<init-param>
<param-name>org.apache.olingo.odata2.path.split</param-name>
<param-value>1</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ODataServlet</servlet-name>
<url-pattern>/odata/v2/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>package</param-name>
<param-value>com.********.s4sdk</param-value>
</context-param>
<listener>
<listener-class>
com.sap.cloud.sdk.service.prov.v2.rt.core.web.ServletListener
</listener-class>
</listener>
</web-app>
Thanks - the error in web.xml that IntelliJ showed disappeared when I put load-on-startup behind the init-param entries.
When I use this URL within Chrome: https://masssalesorders2appli********.us3.hana.ondemand.com/masssalesorders2-application/odata/v2/CFMassSalesOrdersSrv/$metadata, the browser returns "Service not available".
The Cloud Platform 'Default Trace' log has 3 rows - each message for each row follows:
2019 04 02 14:01:46#+00#ERROR#com.sap.cloud.sdk.service.prov.v2.rt.cdx.CDXRuntimeDelegate##anonymous#https-jsse-nio-8041-exec-6#na#********#masssalesorders2application#web#********#na#na#na#na#No Runtime Providers present for the URL and languageCFMassSalesOrdersSrv
2019 04 02 14:01:46#+00#ERROR#com.sap.cloud.sdk.service.prov.v2.rt.cdx.CDXRuntimeDelegate##anonymous#https-jsse-nio-8041-exec-6#na#********#masssalesorders2application#web#********#na#na#na#na#No Runtime Providers present for the URL and languageCFMassSalesOrdersSrv
2019 04 02 14:01:46#+00#ERROR#com.sap.cloud.sdk.service.prov.v2.rt.core.CloudSDKODataErrorCallback##anonymous#https-jsse-nio-8041-exec-6#na#********#masssalesorders2application#web#********#na#na#na#na#Request URL: /masssalesorders2-application/odata/v2/CFMassSalesOrdersSrv/$metadata
StatusCode:500 org.apache.olingo.odata2.api.exception.ODataInternalServerErrorException: Service unavailable.
at org.apache.olingo.odata2.core.servlet.ODataServlet.createServiceUnavailableResponse(ODataServlet.java:373)
at org.apache.olingo.odata2.core.servlet.ODataServlet.handleRequest(ODataServlet.java:210)
at org.apache.olingo.odata2.core.servlet.ODataServlet.handle(ODataServlet.java:115)
at org.apache.olingo.odata2.core.servlet.ODataServlet.service(ODataServlet.java:85)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomee.webservices.CXFJAXRSFilter.doFilter(CXFJAXRSFilter.java:83)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.openejb.server.httpd.EEFilter.doFilter(EEFilter.java:65)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.sap.core.communication.server.CertValidatorFilter.doFilter(CertValidatorFilter.java:157)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.sap.cloud.sdk.cloudplatform.servlet.RequestContextServletFilter.lambda$doFilter$0(RequestContextServletFilter.java:197)
at com.sap.cloud.sdk.cloudplatform.servlet.RequestContextCallable.call(RequestContextCallable.java:131)
at com.sap.cloud.sdk.cloudplatform.servlet.RequestContextServletFilter.doFilter(RequestContextServletFilter.java:209)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.sap.cloud.sdk.cloudplatform.security.servlet.HttpCachingHeaderFilter.doFilter(HttpCachingHeaderFilter.java:82)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.sap.cloud.sdk.cloudplatform.security.servlet.HttpSecurityHeadersFilter.doFilter(HttpSecurityHeadersFilter.java:42)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.filters.RestCsrfPreventionFilter.doFilter(RestCsrfPreventionFilter.java:113)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
at com.sap.core.connectivity.jco.session.ext.RequestTracker.invoke(RequestTracker.java:55)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:610)
at com.sap.cloud.runtime.impl.bridge.security.AbstractAuthenticator.invoke(AbstractAuthenticator.java:206)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.tomee.catalina.OpenEJBSecurityListener$RequestCapturer.invoke(OpenEJBSecurityListener.java:97)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
at com.sap.core.tenant.valve.TenantValidationValve.invokeNextValve(TenantValidationValve.java:182)
at com.sap.core.tenant.valve.TenantValidationValve.invoke(TenantValidationValve.java:97)
at com.sap.js.statistics.tomcat.valve.RequestTracingValve.callNextValve(RequestTracingValve.java:113)
at com.sap.js.statistics.tomcat.valve.RequestTracingValve.invoke(RequestTracingValve.java:59)
at com.sap.core.js.monitoring.tomcat.valve.RequestTracingValve.invoke(RequestTracingValve.java:27)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:836)
When I use the same URL in Postman with 'GET', no rows appear in the 'Default Trace', but a row does appear in 'HTTP Access Log' - it returns '200', but the metadata is not returned. Since this is my first project for creating an OData v2 service that accesses an S/4HANA Cloud API on the back-end, I'm not sure if I have this set up right:
Here is the start of the java code:
#WebServlet("/salesordercreate")
public class MassSalesOrdersServlet extends HttpServlet
{
private static final Logger logger = CloudLoggerFactory.getLogger(MassSalesOrdersServlet.class);
#Create(serviceName = "CFMassSalesOrdersSrv", entity = "MassSalesOrderType")
public CreateResponse createMassSalesOrders(CreateRequest createRequest)
{
MassSalesOrdersEntityType massSalesOrderData = createRequest.getDataAs(MassSalesOrdersEntityType.class);
.
.
.
try {
SalesOrder salesOrderPosted = new SalesOrderCreateFluentHelper("", salesOrder).execute(new ErpConfigContext("S4_Sandbox_Sales_Orders"));
logger.error(salesOrderPosted.getSalesOrder());
MassSalesOrdersEntityType massSalesOrderCreated = new MassSalesOrdersEntityType();
massSalesOrderCreated.setSalesOrderNbrStart(salesOrderPosted.getSalesOrder());
.
.
.
return CreateResponse.setSuccess()
.setData(massSalesOrderCreated).response();
}

You want to implement your own custom handler for a service defined with the SAP Cloud Application Programming Model.
Such a custom handler has to be defined in a plain Java class, not a servlet. The programming model brings its own servlet that handles all requests to the OData service (as you have defined in your web.xml).
Please remove the servlet-specific parts of your class definition (WebServlet annotation + super class).
Assuming that everything else like service definition in CDS is set up correctly, the following implementation of the custom handler should work:
public class MassSalesOrdersServlet
{
#Create(serviceName = "CFMassSalesOrdersSrv", entity = "MassSalesOrderType")
public CreateResponse createMassSalesOrders(CreateRequest createRequest)
{
// your implementation goes here
}
}
The help pages give more details on custom logic in the SAP Cloud Application Programming Model
Regarding your implementation using the OData virtual data model of the SAP S/4HANA Cloud SDK: please use the service to make the create request, instead of instantiating the fluent helper directly:
new DefaultSalesOrderService().createSalesOrder(salesOrder).execute(...)

Related

Jersey SSE not working with Tomcat 7

Frustrated, i am posting this question. I am sure I have surfed enough to know that the proper answer is not discussed so far. But if the case is the contrary, please accept my Apologies and share with me the apt forum link.
I am testing the concepts of SSE broadcast using Jersey SSE API.
I am not using Maven or anything. Because the pet project i am working on, was started way before i became familiar with Maven, hence i manually add Jar files to the Web-Inf lib folder
I have the following relevant jars-
2/28/2016 06:58 PM 85,147 javax.json-1.0.4.jar
12/28/2016 06:58 PM 85,353 javax.servlet-api-3.0.1.jar
12/28/2016 06:58 PM 115,534 javax.ws.rs-api-2.0.1.jar
12/28/2016 06:58 PM 100,146 jaxb-api-2.2.7.jar
12/28/2016 06:58 PM 117,090 jersey-client-2.2.jar
12/28/2016 06:58 PM 600,514 jersey-common-2.2.jar
12/28/2016 06:58 PM 52,819 jersey-container-servlet-core-2.2.jar
12/28/2016 06:58 PM 18,107 jersey-container-servlet.jar
12/28/2016 06:58 PM 971,310 jersey-guava-2.24.1.jar
12/28/2016 06:58 PM 30,495 jersey-media-sse.jar
12/28/2016 06:58 PM 801,094 jersey-server-2.2.jar
My 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"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
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>SDTP-SS-UK-ERP</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/struts/*</url-pattern>
</filter-mapping>
<!-- Jersey Support Configuration for RestFul WebServices -->
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<!-- <servlet-name>jersey-servlet</servlet-name> -->
<servlet-class>
org.glassfish.jersey.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.rest.services,com.sse.services</param-value>
</init-param>
<!--
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
-->
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<!-- <servlet-name>jersey-servlet</servlet-name> -->
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
My Test SSE registration file. I use this to register for the SSE:
#Singleton
#Path("/sse")
public class SseTest extends ResourceConfig
{
public SseTest() {
super(SseTest.class, SseFeature.class);
}
public SseBroadcaster BROADCASTER = new SseBroadcaster();
#GET
#Path("/getSSE")
#Produces(SseFeature.SERVER_SENT_EVENTS)
public EventOutput getMessageQueue()
{
EventOutput eventOutput = new EventOutput();
this.BROADCASTER.add(eventOutput);
System.out.println(eventOutput.toString());
return eventOutput;
}
//After this is registered, i trigger broadcast via another service-
#GET
#Path("/test2/{id}")
#Produces(MediaType.TEXT_PLAIN)
//#Consumes(MediaType.TEXT_PLAIN)
public String addMessage(#PathParam("id") final String msg) throws IOException
{
String misg= msg+"\\n\\n";
OutboundEvent.Builder eventBuilder = new OutboundEvent.Builder();
OutboundEvent event = eventBuilder.mediaType(MediaType.TEXT_PLAIN_TYPE).data(String.class, misg).build();
System.out.println(event.getData());
BROADCASTER.broadcast(event);
return "Message '" + msg + "' has been broadcast.";
}
Now i will share what happens in Chrome, or firefox:
When i am calling the service getSSE, the browser is registering event-stream and even there is a tab eventStream in the network details with a blank table- id, type, data.
When i call the service /test2/10, it shows 200 OK for that and the response is displayed in the browser.
In the getSSE tab, the first getSSE shows as complete and another getSSE comes up as pending.
But the eventsource data is still zero.
After calling test2 twice here is the result:
getSSE 200 eventsource sse.html:-Infinity 149 B 35.41 s
getSSE 200 eventsource Other 149 B 11.0 min
getSSE 200 eventsource Other 144 B Pending
Can someone please point out why i am not getting data? I am not getting any runtime errors in Server End Java.
The server is Tomcat 7.0.69
Java is JDK 1.7
Please help me make this work.. I am losing sleep out of curiosity where i am going wrong
Issue solved
Problem with Library versions

java.lang.IllegalStateException: Could not find backup for factory javax.faces.context.FacesContextFactory

I'm getting the java.lang.IllegalStateException: Could not find backup for factory javax.faces.context.FacesContextFactory. when I deploy my webapp as a .war. Does anyone have an idea where to begin looking for the root cause of this problem? The application runs as expected in the Eclipse IDE, but when exported as a war for deploying on the publicly available stand-alone TomEE environment, it fails.
Many thanks.
My configuration:
Apache TomEE - WebProfile 1.6.0.2
JSF 2.2.7 (com.sun.faces)(Mojarra lib 2.2.0) <-- This may be a problem? But why does the app run in the Eclipse environment but not the stand-alone TomEE?
Maven 4.0.0
java.lang.IllegalStateException: Could not find backup for factory javax.faces.context.FacesContextFactory.
javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:1004)
javax.faces.FactoryFinder.getFactory(FactoryFinder.java:316)
javax.faces.webapp.FacesServlet.init(FacesServlet.java:302)
org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:45)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
java.lang.Thread.run(Thread.java:744)
The web.xml:
<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>ProjName</display-name>
<welcome-file-list>
<welcome-file>login.xhtml</welcome-file>
</welcome-file-list>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<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>
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.forceLoadConfiguration</param-name>
<param-value>true</param-value>
</context-param>
<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>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
The jars that are exported in the .war WEB-INF/lib directory:
WEB-INF/lib/javax.faces.jar
WEB-INF/lib/javax.faces-api-2.2.jar
WEB-INF/lib/jsf-api-2.2.7.jar
WEB-INF/lib/jsf-impl-2.2.7.jar
WEB-INF/lib/poi-3.10-FINAL.jar
WEB-INF/lib/commons-codec-1.5.jar
WEB-INF/lib/poi-ooxml-3.10-FINAL.jar
WEB-INF/lib/poi-ooxml-schemas-3.10-FINAL.jar
WEB-INF/lib/xmlbeans-2.3.0.jar
WEB-INF/lib/stax-api-1.0.1.jar
WEB-INF/lib/dom4j-1.6.1.jar
WEB-INF/lib/xml-apis-1.0.b2.jar
WEB-INF/lib/cxf-bundle-jaxrs-2.7.11.jar
WEB-INF/lib/woodstox-core-asl-4.2.1.jar
WEB-INF/lib/stax2-api-3.1.4.jar
WEB-INF/lib/xmlschema-core-2.1.0.jar
WEB-INF/lib/geronimo-javamail_1.4_spec-1.7.1.jar
WEB-INF/lib/wsdl4j-1.6.3.jar
WEB-INF/lib/jaxb-impl-2.1.13.jar
WEB-INF/lib/jetty-server-8.1.14.v20131031.jar
WEB-INF/lib/jetty-continuation-8.1.14.v20131031.jar
WEB-INF/lib/jetty-http-8.1.14.v20131031.jar
WEB-INF/lib/jetty-io-8.1.14.v20131031.jar
WEB-INF/lib/jetty-util-8.1.14.v20131031.jar
WEB-INF/lib/jetty-security-8.1.14.v20131031.jar
WEB-INF/lib/slf4j-api-1.7.6.jar
WEB-INF/lib/geronimo-servlet_3.0_spec-1.0.jar
WEB-INF/lib/javax.ws.rs-api-2.0-m10.jar
WEB-INF/lib/postgresql-9.3-1101-jdbc41.jar
WEB-INF/lib/commons-httpclient-3.1.jar
WEB-INF/lib/commons-logging-1.0.4.jar
WEB-INF/lib/hamcrest-all-1.3.jar
WEB-INF/lib/junit-4.11.jar
WEB-INF/lib/hamcrest-core-1.3.jar
WEB-INF/lib/httpclient-4.3.3.jar
WEB-INF/lib/httpcore-4.3.2.jar
WEB-INF/lib/commons-dbcp2-2.0.jar
WEB-INF/lib/commons-pool2-2.2.jar
WEB-INF/lib/mockito-core-1.9.5.jar
WEB-INF/lib/objenesis-1.0.jar
I resolved this by removing the parameter from the web.xml file.
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
Removing the above text, rebuilding, exporting the war from Eclipse and deploying with the Tomcat Web Application Manager UI resolved the problem. Apparently, one of the jsf jars has this code built-in since http://java.sun.com/xml/ns/javaee/web-app_3_0 . I don't know this to be a fact, but read it in could not find Factory: javax.faces.context.FacesContextFactory. The difference here being that I removed the parameter instead of adding it.
I resolved this issue by removing the web.xml file and put these two methods in the Spring configuration file.
#Bean
public ServletContextInitializer servletContextCustomizer() {
return new ServletContextInitializer() {
#Override
public void onStartup(ServletContext sc) throws ServletException {
sc.setInitParameter(Constants.ContextParams.THEME, "bootstrap");
sc.setInitParameter(Constants.ContextParams.FONT_AWESOME, "true");
sc.setInitParameter(ProjectStage.PROJECT_STAGE_PARAM_NAME,ProjectStage.Development.name());
sc.setInitParameter("com.sun.faces.forceLoadConfiguration", "true");
sc.setInitParameter("contextConfigLocation", "test");
}
};
}
#Bean
public ServletRegistrationBean servletRegistrationBean() {
FacesServlet servlet = new FacesServlet();
ServletRegistrationBean registration = new ServletRegistrationBean(servlet, "*.jsf");
registration.setName("Faces Servlet");
registration.addUrlMappings("*.jsf");
registration.setMultipartConfig(new MultipartConfigElement((String) null));
registration.setEnabled(true);
registration.setLoadOnStartup(1);
return registration;
}

Spring JavaConfig JPA issue - " No bean named 'entityManagerFactory' is defined"

I'm in the process of converting XML based configuration for a Spring Java Web project to JavaConfig.
I'm using JPA. So I created an additional JavaConfig class with the necessary configuration. But the JPA configuration fails for some reason.
Here is my [web.xml][1]
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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_2_5.xsd">
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<!-- Configuration locations must consist of one or more comma- or space-delimited
fully-qualified #Configuration classes. Fully-qualified packages may also be
specified for component-scanning -->
<!-- <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.my.contoso.spring.contosoJPA</param-value>
</context-param>-->
<!-- Bootstrap the root application context as usual using ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Declare a Spring MVC DispatcherServlet as usual -->
<servlet>
<servlet-name>restservices</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext -->
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<!-- Again, config locations must consist of one or more comma- or space-delimited
and fully-qualified #Configuration classes -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.my.contoso.spring.contosoConfig</param-value>
</init-param>
</servlet>
<!--
This Servlet mapping means that this Servlet will handle all incoming requests
-->
<servlet-mapping>
<servlet-name>restservices</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- for CORS -->
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, HEAD, POST, PUT, DELETE, OPTIONS</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>Content-Type, X-Requested-With, Origin, Accept</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- End for CORS -->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<filter>
<filter-name>OpenEntityManagerFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
<init-param>
<param-name>entityManagerFactoryBeanName</param-name>
<param-value>entityManagerFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>OpenEntityManagerFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- <resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/contosoDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>-->
</web-app>
Here is my primary [JavaConfig class][2]
#Configuration
#EnableWebMvc
//#ImportResource("contoso-jpa.xml") //Import any existing xml context files
#Import(contosoJPA.class)
//#EnableTransactionManagement //substitute for <tx:annotation-driven/>
#ComponentScan({"com.my.contoso.webservices.rest", "com.my.contoso.services,com.my.contoso.dao"})
public class contosoConfig {
}
And Here's the JavaConfig class with [JPA config][3]
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories //(basePackages = { "com.my.contoso.domain" })
public class contosoJPA {
#Bean
public DataSource dataSource() {
// return new EmbeddedDatabaseBuilder().setType(H2).build();
DriverManagerDataSource ds = new DriverManagerDataSource();
try {
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUsername("root");
ds.setPassword("");
ds.setUrl("jdbc:mysql://localhost:3306/contosodb");
} catch (Exception e) {
// logger.error(e.getMessage());
System.out.println(e);
}
return ds;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource);
lef.setJpaVendorAdapter(jpaVendorAdapter);
lef.setPackagesToScan("com.my.contoso.domain");
lef.setPersistenceUnitName("contosoPU");
return lef;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(false);
hibernateJpaVendorAdapter.setGenerateDdl(true);
hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);
// hibernateJpaVendorAdapter.setDatabase(Database.H2);
return hibernateJpaVendorAdapter;
}
#Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager();
}
}
Full Stack Trace:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:570)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1108)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:278)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1121)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.lookupEntityManagerFactory(OpenEntityManagerInViewFilter.java:222)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.lookupEntityManagerFactory(OpenEntityManagerInViewFilter.java:205)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:152)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:179)
at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:241)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2430)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2419)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:570)
'entityManagerFactory' is declared in the [web.xml][1]. The error says that a bean with such name doesn't exist. But I did include it in the [JPA config][3] file. So I'm guessing that the beans in the JPA javaConfig file are not getting picked up. Wondering where the configuration is failing.
Why did you comment out
<!-- Configuration locations must consist of one or more comma- or space-delimited
fully-qualified #Configuration classes. Fully-qualified packages may also be
specified for component-scanning -->
<!-- <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.uhsarp.billrive.spring.BillriveJPA</param-value>
</context-param>-->
?
It seems to me like that root context should be loaded and made available to the whole application through the ContextLoaderListener. That context-param needs to be available so that the root context has a source from which to load bean definitions.
i would try to remove parameters and call bean methods manually:
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource());
lef.setJpaVendorAdapter(jpaVendorAdapter());
lef.setPackagesToScan("com.my.contoso.domain");
lef.setPersistenceUnitName("contosoPU");
return lef;
}
then
try to debug/sout if spring get to any method from this configuration class.
Maybe mixing web.xml configuration with java config is not the best idea? Did you consider to migrate it? :)

Spring Mobile inside AuthenticationFailureHandler not found

I am development success and failure handlers in Spring Security.
Depends device type I must show one html view or send one json response. To this purpose I use Spring Mobile, but when I create Device object with HtttpServletRequest not found. Some idea?
web.xml
<filter>
<filter-name>deviceResolverRequestFilter</filter-name>
<filter-class>org.springframework.mobile.device.DeviceResolverRequestFilter</filter-class>
</filter>
ApplicationContext.xml
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.mobile.device.DeviceWebArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
Class
public class AuthFailureHandler implements AuthenticationFailureHandler{
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException ae) throws IOException, ServletException {
Device device = DeviceUtils.getCurrentDevice(request);
if(device.isNormal()){
response.sendRedirect(response.encodeRedirectURL("./userNoAuth"));
} else {
response.sendRedirect(response.encodeRedirectURL("./rest/userNoAuth"));
}
}
}
Error
java.lang.NullPointerException at com.myapp.security.handler.AuthFailureHandler.onAuthenticationFailure(AuthFailureHandler.java:19)
UPDATE:
I am change .getCurrentDevice(HttpServletRequest) method to getRequiredCurrentDevice(HttpServletRequest).
Now I get this error.
java.lang.IllegalStateException: No currenet device is set in this request and one is required - have you configured a DeviceResolvingHandlerInterceptor?
Verify your web.xml contains a filter-mapping for the deviceResolverRequestFilter. The following is a working example from the Spring Mobile Samples repository. Hope that helps!
https://github.com/SpringSource/spring-mobile-samples/tree/master/lite-device-resolver-xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Use the DeviceResolverRequestFilter OR the DeviceResolverHandlerInterceptor in the servlet-context.xml -->
<filter>
<filter-name>deviceResolverRequestFilter</filter-name>
<filter-class>org.springframework.mobile.device.DeviceResolverRequestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>deviceResolverRequestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

extending SpringBeanAutowiringSupport with GlassFish 3.1

I'm trying to expose my web service by extending SpringBeanAutowiringSupport. I'm using GlassFish 3.1 and Spring 3.0.5.RELEASE.
I'm following the tutorial here.
However, when I go to the URL of my web service I get a ClassCastException.
Any ideas on what I'm missing or doing wrong?
WARNING: StandardWrapperValve[GreetingService]: PWC1382: Allocate exception for servlet GreetingService
java.lang.ClassCastException: com.service.GreetingServiceEndpoint cannot be cast to javax.servlet.Servlet
at com.sun.enterprise.web.WebContainer.createServletInstance(WebContainer.java:702)
at com.sun.enterprise.web.WebModule.createServletInstance(WebModule.java:1958)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1263)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:1070)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:189)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:326)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:227)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:170)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:822)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:719)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1013)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:680)
Endpoint
#WebService (serviceName="GreetingService")
public class GreetingServiceEndpoint extends SpringBeanAutowiringSupport {
#Autowired
private GreetingService greetingService;
#WebMethod
public String sayHello () {
return greetingService.sayHello();
}
}
Service
#Service ("greetingService")
public class GreetingService {
public String sayHello () {
return "Hello from Greeting Service";
}
}
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" 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_3_0.xsd"
id="WebApp_ID" version="3.0" metadata-complete="true">
<display-name>Archetype Created Web Application</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>GreetingService</servlet-name>
<servlet-class>com.service.GreetingServiceEndpoint</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GreetingService</servlet-name>
<url-pattern>/GreetingService</url-pattern>
</servlet-mapping>
</web-app>
Your class: com.service.GreetingServiceEndpoint is not an instance of javax.servlet.Servlet. You can't put it into your web.xml as a servlet. To run JAX-WS web services, JAX-WS servlet has to be declared in web.xml: com.sun.xml.ws.transport.http.servlet.WSServlet this servlet will serve the requests to your web service.
The full servlet declaration should look something like this:
<servlet>
<servlet-name>Greeting</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Greeting</servlet-name>
<url-pattern>/services/Greeting</url-pattern>
</servlet-mapping>
Your com.service.GreetingServiceEndpoint class should be defined in sun-jaxws.xml file, something like this:
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">
<endpoint name="Greeting" implementation="com.service.GreetingServiceEndpoint" url-pattern="/services/Greeting"/>
</endpoints>
This file has to be added into WEB-INF of your web app. Take a look at my post here. It should be helpful.
There's no need of registering com.service.GreetingServiceEndpoint as a Servlet in web.xml; as it doesn't extends HttpServlet.

Resources