I am building a web app using java ee as backend and angular as frontend. As application server i have chosen Wildfly 13. As a build tool for backend I have chosen Maven. I have created this structure for the project :
-Project
---Project-ear
---Project-model
---Project-service
---Project-service-api
Neither of this modules packages a war file, I package 3 jars and in the end I assemble them in an ear file using
"Project-ear"
I have tried to consume the exposed service inside
"Project-service"
but I cant. It seems I don't set the right url. Can somebody help me please?
I have tried to access the following urls:
http://localhost:8080/Project-ear/Project-service/resources/test/testDtos/,
http://localhost:8080/resources/test/testDtos/
I have created the RestActivator class :
#ApplicationPath("/resources")
public class RestActivator extends Application {
}
And I have created a Resource class :
#Path("/test")
public class TestResource {
#GET
#Path("/testDtos")
#Produces(MediaType.APPLICATION_JSON)
public Response getWorkflowDiagram() {
TestDto testDto = new TestDto();
testDto.setFirstName("Test");
testDto.setLastName("Test");
return Response.ok(testDto).build();
}
}
I don't get any error message, I just can't access the URL endpoint.
When you configure the Application Server (Wildfly) and add the ear artifact, it creates a target folder in your ear-folder. There you can find a file called application.xml. You have to set the context-root like that:
<?xml version="1.0" encoding="UTF-8"?>
<application 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/application_7.xsd"
version="7">
<module>
<web>
<web-uri>test.war</web-uri>
<context-root>/api</context-root>
</web>
</module>
</application>
Your URL depends on what you have set in context-root in application.xml and how have set the application path in your root class (RestActivator).
In this example:
localhost:8080/api/resources
And to get access to your method in TestResource:
localhost:8080/api/resources/test/testDtos
Got a WAR Maven module with a REST Client, implemented as #Stateless EJB) in a module (say) "mycompany-client".
This REST Client invoke an EJB implemented in a EAR module, with a JAR module inside (say) "mycompany-business-service".
(EAR and JAR module are under a parent POM module)
WAR and EAR are running on a Weblogic 12C (Java EE 6).
But IT COULD BE ON DISTINCT SERVERS.
My module "mycompany-client" (war)
REST CLIENT
#Stateless
#Path("clusters")
public class ClusterResource {
#EJB
ClusterService service;
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<Cluster> getItems() {
return service.getAllClusters();
}
[...]
My EJB module "mycompany-business-service" (a JAR in an EAR)
EJB (with a Remote Business Interface)
Remote Interface (ClusterService)
#Remote
public interface ClusterService {
public List<Cluster> getAllClusters();
}
Implementation (ClusterServiceBean)
#Stateless
#Remote(ClusterService.class)
public class ClusterServiceBean implements ClusterService {
#Override
public List<Cluster> getAllClusters() {
// Do the job
return ...;
}
[...]
In the dependencies of my WAR (pom.xml), i have to declare a dependecy to my "mycompany-business-service" jar :
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>mycompany-business-services</artifactId>
<version>1.0.0</version>
<scope>provided</scope> <== with or without
</dependency>
So what ?...
1) Choice 1 : using "provided" scope : ?
As "mycompany-business-service" is already deployed on my Weblogic server, i thought to use "provided" scope.
But if i do this, the deploy (via the great "wls-maven-plugin") fails with a ClassNotFoundException concerning the service EJB to be injected !
2) Choice 2 : no "provided" scope, jar embedded ?
In this case, the injection and the call to EJB works perfectly... but but : the invoked EJB is the local/embedded one, NOT THE REMOTE ONE !
Finally, my question :
Howto package WAR with a REST Client for Remote EJB to be injected ?
I Can't seem to figure it out. tried to use annotations and web.xml to configure paths to webcontent but keep getting unknown resources.
Jersey main:
#ApplicationPath("/")
public class App extends PackagesResourceConfig {
public App() {
super("webapp.resources");
}
}
Jersey default path "/": (hello world works! index.html\jsp does not)
#Path("/")
#Produces(MediaType.TEXT_HTML)
public class RootResource
{
#GET
public String index(#Context HttpServletRequest request) {
return "hello world";
}
}
What I've tried:
multiple web.xml config
serving viewables (error cannot resolve template index.jsp)
what do you think can be a solution to serve pages like html or jsp?
is there a way to do it with jersey (no spring!) and viewable\templates?
to answer my question. futuretelematics's solution should work for most people. it is a known and valid solution. so WHY didn't work when i did it:
question 1:
after much fiddling around i discovered that once i changed the application root path from "/" to "/api" (or /???) suddenly everything started to play along. must be a jersey thing. i read somewhere that in order to make the "/" work you should map with filter in the web.xml. I would love to hear if anyone has done that successfully.
so right now it serves my initial page with JSP. that page i can manipulate with jsons in a rest fashion.
question 2:
making #viewable work was just a matter of creating the right folder structure path in WebContent (com/webapp/model/index(<-- jsp)). that's how the viewable page redirect works.
This should be easy; try the following:
The /WEB-INF/web.xml file:
<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"
version="3.0">
<display-name>Your REST end Point</display-name>
<!-- /////////////////////// JERSEY (NO SPRING) ///////////////////////// -->
<servlet>
<servlet-name>MyRESTEndPoint</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<!- Package where jersey will scan for resources ->
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.mycompany</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyRESTEndPoint</servlet-name>
<url-pattern>/MyRESTEndPoint/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
AT package com.mycompany (look at at the web.xml) place the Application class:
package com.mycompany;
public class MyApp
extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
s.add(MyResource.class);
// ... add other resources
return s;
}
}
Create the resource like:
#Path("myResourcePath")
public class R01ERESTResourceForStructure {
#GET #Path("{myResourceId}")
#Produces(MediaType.APPLICATION_XML)
public Response load(#PathParam("myResourceId") final String id) {
....
}
}
Your urls should be: like /MyRESTEndPoint/myResourcePath/myResourceId
If you're using SPRING or GUICE the web.xml should be a bit different
Jersey provides support for JSP templates in jersey-mvc-jsp extension module
check out the official doc
I have an app that runs fine on jboss7, it uses jee6 apis: jax-rs and CDI. Due to production limitations I was asked to adapt it to run on Jboss 5.1.0. To make things easy I created a minimal application, with only one service and one injection. It works fine on jb7, and I had to add the libs that are not provided for the jboss5 version.
jax-rs worked fine, I added RestEasy and declared the RestEasy servlet on the web.xml.
For CDI I included Weld, to work on servlet mode, since the application does not have servlets. Following the docs, I included the listener on the web.xml, and then found on a jboss forum that another listener is necessary to register the BeanContext to the jboss jndi.
So what I have is:
<?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">
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
<listener>
<listener-class>org.jboss.weld.environment.servlet.BeanManagerResourceBindingListener</listener-class>
</listener>
<servlet>
<servlet-name>resteasy-servlet</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>br.com.bvmf.services.ApplicationConfig</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
For the build I am using Gadle, but just to have a better understanding for not I am inserting most of the jars manually for now:
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'war'
webAppDirName = 'WebContent'
repositories {
mavenCentral()
flatDir name:'EasyRestJars',dirs:'libs'
}
dependencies {
compile(
[name : 'weld-servlet', version : '2.0.0.SP1-jboss5'],
[name : 'jaxrs-api', version : '2.3.6.Final'],
[name : 'jackson-core-asl', version : '1.9.9'],
[name : 'jackson-jaxrs', version : '1.9.9'],
[name : 'jackson-mapper-asl', version : '1.9.9'],
[name : 'resteasy-jackson-provider', version : '2.3.6.Final'],
[name : 'resteasy-jaxb-provider', version : '2.3.6.Final'],
[name : 'resteasy-jaxrs', version : '2.3.6.Final'],
[name : 'scannotation', version : '1.0.3']
)
providedCompile(
[group: 'org.slf4j', name: 'slf4j-api', version: '1.5.6'],
[group: 'javaee', name: 'javaee-api', version: '5' ]
)
testCompile group: 'junit', name: 'junit', version: '4.+'
}
test {
systemProperties 'property': 'value'
}
war{
exclude 'WEB-INF/lib/*'
}
Now the three classes:
Tha application config just returns the service:
#ApplicationPath("min")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
resources.add(br.com.bvmf.services.HelloWorldResource.class);
return resources;
}
}
The bean that should be injected:
public class HelloProvider {
public String getString() {
return "Injected Hello";
}
}
And the service itself:
#Path("/helloworld")
public class HelloWorldResource {
#Inject
private HelloProvider provider;
#GET
public String getMessage() {
//This is where I get a null pointer
return provider.getString();
}
}
So the bean is not injected, just that. During the deploy, the log reads:
2013-06-04 15:24:31,371 INFO [org.jboss.webbeans.bootstrap.WebBeansBootstrap] (HDScanner) Web Beans 1.0.0.PREVIEW1
2013-06-04 15:24:32,898 INFO [org.jboss.web.tomcat.service.deployers.TomcatDeployment] (HDScanner) deploy, ctxPath=/min-cil-1.0-SNAPSHOT
2013-06-04 15:24:33,417 INFO [org.jboss.weld.Version] (HDScanner) WELD-000900 2.0.0 (SP1)
2013-06-04 15:24:33,774 INFO [org.jboss.weld.Bootstrap] (HDScanner) WELD-000101 Transactional services not available. Injection of #Inject UserTransaction not available. Transactional observers will be invoked synchronously.
2013-06-04 15:24:34,485 WARN [org.jboss.weld.Bootstrap] (HDScanner) Legacy deployment metadata provided by the integrator. Certain functionality will not be available.
2013-06-04 15:24:34,809 INFO [org.jboss.weld.environment.tomcat.Tomcat6Container] (HDScanner) Tomcat 6 detected, CDI injection will be available in Servlets and Filters. Injection into Listeners is not supported
2013-06-04 15:24:35,750 INFO [org.jboss.weld.environment.servlet.BeanManagerResourceBindingListener] (HDScanner) BeanManager reference bound to java:comp/env/BeanManager
2013-06-04 15:26:13,648 INFO [org.jboss.resteasy.spi.ResteasyDeployment] (http-127.0.0.1-8080-2) Deploying javax.ws.rs.core.Application: class br.com.bvmf.services.ApplicationConfig
There is a note in the weld docs saying that: "Additionally, Weld Servlet supports JBoss EAP 5.1, to do this use the jboss5 variant of Weld Servlet." So I found this version, but it made no difference (besides more problems with slf4j).
I don't think there is any integration with JAX-RS in Weld Servlet - this is only available in Java EE 6. You could look at the way it is done in JBoss AS 6 and try to backport it perhaps? Or look at the CDI and RESTEasy docs to work out how to add it (basically, you need to register some sort of post-construct listener with RESTEasy, and then use CDI APIs to inject the instance).
It seems Weld is not supported on JBoss 5.1 afterall. In the end I changed the dependency injection to Spring with annotations and autowire. Spring played well with RESTEasy, so its all fine now.
I am using JBoss 5 GA, I created a test Session bean, and local interface. I have created a servlet client. I tried to inject the interface in the servlet using #EJB..
But when I call this servlet I got the requested resource is not available!!!! When I comment the //#EJB, the page run successfully, any help please????
Jotnarta
It would have been helpful to add some piece of code in your question, at least the annotations in your EJB, local interface (if you annotated it) and servlet...
Nevertheless, according to the Chapter 11. Introduction to EJB injection in Servlets of the JBoss EJB3 Tutorials, for an EJB module containing an EJB3 SLSB defined like this:
#Stateless(name="calculator")
#Remote(CalculatorRemote.class)
#Local(CalculatorLocal.class)
public class CalculatorBean implements CalculatorRemote, CalculatorLocal
{
...
The local interface can be injected in a Servlet of a web module this way:
private CalculatorLocal calculator;
/**
* Injecting the EJB
*/
#EJB(name = "calculator")
public void setCalculator(CalculatorLocal calculator)
{
this.calculator = calculator;
}
There is an important note in this tutorial that i'm pasting below:
For the injection to take place in a
web module, your web.xml should use
the 2.5 version of the web-app xsd:
<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">