Posts Tagged ‘Tomcat’
Error 403 with Maven 2 deployment
Case
This morning, I tried to redeploy an EAR on a WebLogic 9.2, using Maven 2 and a classical deployment profile. I got this issue:
[ERROR] BUILD ERROR [INFO] ------------------------------------------------------------------------ [INFO] Error executing ant tasks Embedded error: The following error occurred while executing this line: (...) weblogic.deploy.api.internal.utils.DeployerHelperException: The source 'C:\DOCUME~1\myLogin\LOCALS~1\Temp\myApplication-ear.ear' for the application 'my-application-ear' could not be loaded to the server 'http://myServer:1234/bea_wls_deployment_internal/DeploymentService'. Response: '403: Forbidden' for url: 'http://myServer:1234/bea_wls_deployment_internal/DeploymentService'
Yesterday, I got a similar error when I launched a mvn tomcat:deploy
to deploy a WAR on a Tomcat 6.0 server:
[ERROR] BUILD ERROR [INFO] ------------------------------------------------------------------------ [INFO] Cannot invoke Tomcat manager Embedded error: Server returned HTTP response code: 403 for URL: http://myServer:3210/manager/deploy?path=%2FmyWebArchive&war=&update=true
Quick Fix
Running Maven2 in offline line, ie adding the option "-o"
, allows me to redeploy both the EAR on WebLogic and the WAR on Tomcat.
eg: mvn tomcat:deploy -o
I keep on investigating on this matter. I think there is an issue on the DNS. Indeed, when I deploy locally to my own machine myServer
(ie with its network name), this error is raised, but when I deploy to localhost
the build is successful.
GWT: call a remote EJB with Spring lookup
Abstract
Let’s assume you have followed the article “Basic RPC call with GWT“. Now you would like to call an actual EJB 2 as remote, via a Spring lookup.
Let’s say: you have an EJB MyEntrepriseComponentEJB
, which implements an interface MyEntrepriseComponent
. This EJB, generates a remote MyEntrepriseComponentRemote
.
Entry Point
In myApplication.gwt.xml
entry point file, after the line:
<inherits name='com.google.gwt.user.User'/>
add the block:
<inherits name='com.google.gwt.user.User' /> <inherits name="com.google.gwt.i18n.I18N" /> <inherits name="com.google.gwt.http.HTTP" />
Add the line:
<servlet path='/fooService.do'/>
Client
Under the *.gwt.client
folder:
Update the service interface. Only the annotation parameter is amended:
@RemoteServiceRelativePath("services/fooService") public interface FooService extends RemoteService { public String getHelloFoo(String fooName); }
You have nothing to modify in asynchronous call interface (FooServiceAsync
).
Server
Under the *.gwt.server folder
, update the implementation for service interface:
Change the super-class, replacing RemoteServiceServlet
with GWTSpringController
:
public class FooServiceImpl extends GWTSpringController implements FooService { public FooServiceImpl() { // init } }
Add new field and its getter/setter:
// retrieved via Spring private myEntrepriseComponent myEntrepriseComponent; public myEntrepriseComponent getMyEntrepriseComponent() { return myEntrepriseComponent; } public void setmyEntrepriseComponent(myEntrepriseComponent _myEntrepriseComponent) { myEntrepriseComponent = _myEntrepriseComponent; }
Write the actual call to EJB service:
public String getHelloFoo(String fooName) { return myEntrepriseComponent.getMyDataFromDB(); } }
web.xml
Fill the web.xml
file:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <!-- Spring --> <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> <servlet> <servlet-name>gwt-controller</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>gwt-controller</servlet-name> <url-pattern>/myApplication/services/*</url-pattern> </servlet-mapping> <!-- Default page to serve --> <welcome-file-list> <welcome-file>MyApplicationGwt.html</welcome-file> </welcome-file-list> </web-app>
JNDI
Add a jndi.properties
file in src/resources folder
:
java.naming.provider.url=t3://localhost:12345 java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory java.naming.security.principal=yourLogin java.naming.security.credentials=yourPassword weblogic.jndi.enableDefaultUser=true
These properties will be used by Spring to lookup the remote EJB. The last option is very important, otherwise you may happen to face issues with EJB if they were deployed under WebLogic.
WEB-INF
In the WEB-INF
folder, add an applicationContext.xml
file:
<?xml version="1.0" encoding="UTF-8"?> <beans> <util:properties id="jndiProperties" location="classpath:jndi.properties" /> <jee:remote-slsb id="myEntrepriseComponentService" jndi-name="ejb.jonathan.my-entreprise-component" business-interface="lalou.jonathan.myApplication.services.myEntrepriseComponent" environment-ref="jndiProperties" cache-home="false" lookup-home-on-startup="false" refresh-home-on-connect-failure="true" /> </beans>
Add a gwt-controller-servlet.xml
file:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean> <property name="order" value="0" /> <property name="mappings"> <value> /fooService=fooServiceImpl </value> </property> </bean> <bean id="fooServiceImpl" class="lalou.jonathan.myApplication.web.gwt.server.FooServiceImpl"> <property name="myEntrepriseComponent" ref="myEntrepriseComponentService" /> </bean> </beans>
Of course, if your servlet mapping name in web.xml
is comoEstasAmigo, then rename gwt-controller-servlet.xml
as comoEstasAmigo-servlet.xml
😉
Build and deploy
Now you can compile, package your war and deploy under Tomcat or WebLogic. WebLogic server may raise an error:
java.rmi.AccessException: [EJB:010160]Security Violation: User: '<anonymous>' has insufficient permission to access EJB
This error is related to the rights required to call a method on the EJB. Indeed, two levels of rights are used by WebLogic: firstly to lookup / instanciate the EJB (cf. the property java.naming.security.principal
we set sooner), and another to call the method itself. In this second case, WebLogic requires an authentication (think of what you do when you login an web application deployed: your login and rights are kept for all the session) to grant the rights. I wish to handle this subject in a future post.
NB: thanks to David Chau and Didier Girard from SFEIR, Sachin from Mumbai team and PYC from NYC.
Basic RPC call with GWT
Let’s assume you have a “Hello World” GWT application. You need emulate a basic RPC call (RMI, EJB, etc.). Here is the program:
Under the *.gwt.client folder
:
Create an service interface:
@RemoteServiceRelativePath("fooService") public interface FooService extends RemoteService { public String getHelloFoo(String totoName); }
Create another interface for asynchronous call. You can notice the method name differs lightly from the one in the other interface:
public interface FooServiceAsync { void getHelloFoo(String fooName, AsyncCallback<String> callback); }
Under the *.gwt.server
folder, create an implementation for service interface:
public class FooServiceImpl extends RemoteServiceServlet implements FooService { public FooServiceImpl() { // TODO init } public String getHelloFoo(String fooName) { // TODO call actual service return "hello world!"; } }
In the web.xml
file, add the following blocks:
<!-- Servlets --> <servlet> <servlet-name>fooService</servlet-name> <servlet-class>com.......server.FooServiceImpl</servlet-class> </servlet> <servlet-mapping> <servlet-name>fooService</servlet-name> <url-pattern>/ivargwt/fooService</url-pattern> </servlet-mapping>
The tags content match the argument given as parameter to RemoteServiceRelativePath
annotation above.
From then, in your concrete code, you can instantiate the service and call remote method:
FooServiceAsync fooService = GWT.create(FooService.class); fooService.getHelloFoo("how are you?", new AsyncCallback<String>() { public void onSuccess(String result) { MessageBox.alert("OK", result, null); } public void onFailure(Throwable caught) { MessageBox.alert("ERROR", "rpc call error-" + caught.getLocalizedMessage(), null); } });
Now you can compile, package your war
and deploy under Tomcat or WebLogic.
NB: special to “black-belt GWT guy” David Chau from SFEIR.
Servlet of class org.apache.catalina.servlets.CGIServlet is privileged and cannot be loaded by this web application
Case:
Under Windows / Tomcat 6:
java.lang.SecurityException: Servlet of class org.apache.catalina.servlets.CGIServlet is privileged and cannot be loaded by this web application
Fix:
In the web.xml
file, add the following block:
<context-param> <param-name>privileged</param-name> <param-value>true</param-value> </context-param>