I am having a Session Bean exposed via RESTful interface in JBoss AS7.1.1; That is having both a EJB module and a WAR module, the WAR module having a (maven) dependency on the EJB module; The WAR is just web.xml with RestEasy directives.
(modelled along https://github.com/alexcpn/rest_in_sessionbean )
Stateless
#Path("sessionbean")
public class ControllerRest {
#EJB
Controller mroController;
/**
* Default constructor.
*/
public ControllerRest() {
}
#GET
#Path("/test")
#Produces(MediaType.TEXT_PLAIN)
public String test( ){
return "Hello from Mro SessionBean Jar ";
}
I am intermittently getting 'HTTP Status 500 - Bad arguments passed' error while invoking the REST interface; ( plain REST calls and ones with Query interface). It seems some problem with class loading
as described in -https://community.jboss.org/thread/175629. Looks like a bug in RESTEasy integration to JBOSS.
17:31:28,142 SEVERE [org.jboss.resteasy.core.SynchronousDispatcher] (http--127.0.0.1-8080-4) Failed executing GET /sessionbean/test: org.jboss.resteasy.spi.InternalServerErrorException: Bad arguments passed to public java.lang.String com.nokia.oss.MroControllerRest.test() ( )
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:196) [resteasy-jaxrs-2.3.2.Final.jar:]
at org.jboss.resteasy.core.ResourceMethod.invokeOnTarget(ResourceMethod.java:257) [resteasy-jaxrs-2.3.2.Final.jar:]
at org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:222) [resteasy-jaxrs-2.3.2.Final.jar:]
at org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:211) [resteasy-jaxrs-2.3.2.Final.jar:]
at org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:525) [resteasy-jaxrs-2.3.2.Final.jar:]
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:502) [resteasy-jaxrs-2.3.2.Final.jar:]
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:119) [resteasy-jaxrs-2.3.2.Final.jar:]
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:208) [resteasy-jaxrs-2.3.2.Final.jar:]
I had the same problem. So, i suppose the problem is in old version of library resteasy-jaxrs from JBoss.
All i did is moved to wildfly, but i think it could be fixed with new version of a library.
Related
I want to create a simple JAX-RS REST Service for Wildfly 10. My issue is that my REST Service is not found. Result in browser is 404 not found. I am not sure what exactly the issue is. I get no error or exception in wildfly log file. I am using eclipse neon 3 and wildfly 10. My project is using JAX-RS not resteasy.
Here my project setup and code:
I have created a Dynamic Web Project in Eclipse.
I have set JAX-RS(REST Service) support in the project facets. JAX-RS version is 2.0 (also tried with version 1.1)
I have create a subclass which extends Application (javax.ws.rs.core.Application)
I added the annotation #ApplicationPath("/yoshi-rest") to the class which extends Application.
I have created a class which contains my rest service method. The class itself has the #Path("/StatusService") annotation.
The affected method has the annotations #Get and #Path("/getStatus").
Due to I have the subclass of Application I didn't set the servlet mapping in web.xml.
Here the code:
Subclass of Application(RESTConfig):
#ApplicationPath("/yoshi-rest")
public class RESTConfig extends Application {
}
REST Service class(StatusService):
#Path("/StatusService")
public class StatusService {
#Get
#Path("/getStatus")
public String getStatus() {
return "Yoshi is up and running";
}
}
I can see during startup of wildfly that the subclass RESTConfig is deployed:
11:09:23,777 INFO [org.jboss.resteasy.resteasy_jaxrs.i18n] (ServerService Thread Pool -- 61) RESTEASY002225: Deploying javax.ws.rs.core.Application: class XXXX.yoshi.rest.services.RESTConfig
If I call the rest service url (http://localhost:8080/yoshi-rest/StatusService/getStatus) in browser, I get a '404 - Not found' as result.
Any idea what I am doing wrong?
You need to register service to connect to your RESTConfig:
#ApplicationPath("/yoshi-rest")
public class RESTConfig extends ResourceConfig {
public RESTConfig() {
register(StatusService.class);
}
See more on ResourceConfig configuration options
Standard JAX-RS uses an Application as its configuration class. ResourceConfig extends Application.
Putting the project name in the url solved the issue.
Thanks for help.
Java EE Tutorial is not helpful at all. Internet search was underwhelming.
I have an EJB module that is deployed to glassfish by itself. It has #Local and #Remote annotated iterfaces which are both implemented by the concrete class.
Then i have a REST resource that needs to get a reference to that ejb module and invoke some methods.
Can you give me a barebones, simple example of how that is done? I mean, i can't even inject SessionContext into my rest app, as it crashes... Please, keep it simple.
The ejb should just have a:
public String getMsg(){
return "ohai";
}
The rest service:
#GET
#Produces("text/plain")
public String asd(){
return <the myterious ejb that was injected somehow>.getMsg();
}
Thanks.
Alright, i figured it out. Using NetBeans, but probably applicable to Eclipse. Server - glassfish
Create webapp, an EJB -> call EJB from webapp. All these run inside the same server as separate modules.
First: create an EJB module, it will be deployed on its own:
remote interface:
package main;
import javax.ejb.Remote;
#Remote
public interface YourRemoteInterface{
public String tellMeSomething();
public void otherMethod(); //etc...
}
then create the EJB implementation class:
concrete implementation
package main;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.EJB; //crucial to JNDI lookup
#Remote(RemoteInterface.class)
#Stateless
#EJB(name="java:global:/MYSTUFF", beanInterface=YourRemoteInterface.class)
public class YourConcreteClass implements YourRemoteInterface{
#Override
public String tellMeSomething(){//...} //and do the other methods
}
#EJB name attribute names your bean, that you will use to look it up. Can by any name. For ex: "some-name", or "java:global/YourConcreteClass"
Part two - webapp:
For web app i used a rest service, but surely can be another EJB or a SE client app. For SE client you'd need to set connection info, but that for another life.
#Path("/somePath")
public class Service{
#GET
#Produces("text/plain")
public String qwe(){
try{
javax.naming.InitialCOntext ic = new javax.naming.InitialContext();
YourRemoteInterface rb = (YourRemoteInterface)ic.lookup("java:global:/MYSTUFF");
return rb.tellMeSomething();
} catch (Exception ex) {
return "F*uck your life";
}
}
}
Now, from Project Properties of your webapp, you need to:
1) add the ejb jar file to Libraries so it shows in the Compile tab. I used the "Add project" button
2) Build -> Packaging: add the ejb jar file to WAR content. I used "Add file/folder", where i navigated to NetBeans projects / the EJB module / build / dist
note: you may experience an error when trying to deploy the ejb, or redeploy it. Error name is: java.lang.RuntimeException: Error while binding JNDI name main.RemoteInterface#main.RemoteInterface for EJB RemoteBean . Skipping the vague explanation, to cure it, you need to execute a command in glassfish:
asadmin set server.ejb-container.property.disable-nonportable-jndi-names="true"
Now, you can compile the webapp and deploy it. Should work.
At the end it's that simple. I swear i've eaten the WHOLE ejb section in glassfish tutorial and nowhere do they tell you this stuff. It's so annoying.
I try to build a Java EE 7 app with Rest services and EJB injection.
I created a multi module maven project which I deploy on Glassfish 4. My final EAR contain a JAR with my EJBs, with for example my Rest services definitions :
#Stateless
#Path("countries")
public class CountryRest {
//#EJB
//StockService stockService;
#GET
public Response getCountries() {
//stockService.getAll(); --> firing a NPE, stockService is Null
return Response.ok().build();
}
}
#Stateless
#Remote(IStockService.class)
public class StockService implements IStockService {
#Override
public List<Stock> getAllStock() {
return new ArrayList<Stock>();
}
}
When I deploy my app, I see the following logs which seems ok. Even if I wonder why it defines "java:global" JNDI since by default #Stateless EJB is #Local :
Portable JNDI names for EJB CountryRest: [java:global/GeoData-ear/GeoData-ejb-1.0-SNAPSHOT/CountryRest, java:global/GeoData-ear/GeoData-ejb-1.0-SNAPSHOT/CountryRest!com.tomahim.geodata.rest.CountryRest]
Portable JNDI names for EJB StockService: [java:global/GeoData-ear/GeoData-ejb-1.0-SNAPSHOT/StockService, java:global/GeoData-ear/GeoData-ejb-1.0-SNAPSHOT/StockService!com.tomahim.geodata.services.IStockService]
Then when I'm doing a GET on /rest/countries, the status is 200 as expected but I have a NameNotFoundException / NamingException :
Avertissement: An instance of EJB class, com.tomahim.geodata.rest.CountryRest, could not be looked up using simple form name. Attempting to look up using the fully-qualified form name.
javax.naming.NamingException: Lookup failed for 'java:module/CountryRest' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: No object bound to name java:module/CountryRest]
I see that the lookup for "java:module/ContryRest" is not matching "java:global/.../CountryRest" but what am I doing wrong ?
EDIT 1 : I was able to make #Ejb injection work by placing my Rest definitions ans EJBs in my webapp maven module deploy as a WAR. So it seems that the problem occur only when I deploy my EJB in a JAR. Any idea ? What could be the difference between JAR and WAR deployment ?
It is required by the JAX-RS spec that all REST endpoints must live within your WAR file. Do you really need an EAR file?
I'm working on a simple Java EE Application, using Glassfish.
Everything runs fine, my Entity and Session Beans are working.
I also created some JAX RS Resources to invoke the Session Beans, which also works fine.
Now I'm struggling with Bean Validation.
Let's have a look at a little snippet:
#GET
#Path( "{portaluser}" )
#NotNull
public PortaluserResponse load( #PathParam( "portaluser" ) #NotBlank #Email final String strEmail )
{ ... some implementation ... }
My Jersey Application, which of course extends ResourceConfig looks like this:
public JerseyApplication()
{
packages( PortaluserService.class.getPackage().getName() );
register( JacksonFeature.class );
register( ValidationConfig.class);
property( ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true );
}
In my pom.xml I included following dependency:
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
<version>2.9</version>
</dependency>
If I invoke the REST Service with nonsense data, the validation doesn't kick in.
Why is that? I expect to get a validation error.
I found a jersey-Sample which covers the bean validation stuff. My REST-Resource works within that project.
The only difference is, that jersey-Sample doesn't run in Glassfish, but in a Jetty.
Can it be that jersey bean validation doesn't work when running in a Java EE container?
Would appreciate some hints.
I am new to EJB3 and am missing something when it comes to accessing a #Remote #Stateless bean deployed as an ejb module inside an ear file. I want to access a remote bean in lima.ear from soup.ear.
Here is what I am doing now (somewhat abbreviated):
//deployed under lima.ear
#Remote
#Stateless
public interface LimaBean {
String sayName();
}
I want to put LimaBean in the Soup:
//deployed in soup.ear
#Stateless
public class Soup implements SoupLocal {
#EJB
private LimaBean limaBean;
public String taste() {
return limaBean.sayName();
}
}
When I start JBoss I get the following error:
java.lang.RuntimeException: could not resolve global JNDI name for #EJB for container Soup: reference class: com.example.LimaBean ejbLink: not used by any EJBs
I have had a hard time finding out what this ejbLink is about, if that is the right path to go down.
If I deploy LimaBean as a jar file in jboss then everything works great!
I ran accross an article that had a section called "2.5.3. References between beans in different jars and different ears"
(http://jonas.ow2.org/doc/howto/jboss2_4-to-jonas3_0/html/x111.html)
Example of jboss.xml file for SB_BrowseRegions:
<jboss>
<session>
<ejb-name>SB_BrowseRegions</ejb-name>
<ejb-ref>
<ejb-ref-name>ejb/Region</ejb-ref-name>
<jndi-name>protocol://serverName/directory/RegionHome</jndi-name>
</ejb-ref>
</session>
</jboss>
If I touch the soup.ear, after JBoss starts up then it deploys fine, so I am assuming I need to specify a dependency like the above article says.
But even after it deploys then I get an error when accessing the remote LimaBean:
Caused by: java.lang.IllegalArgumentException: Can not set com.soup.LimaBean field com.soup.Soup.limaBean to $Proxy147
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63)
at java.lang.reflect.Field.set(Field.java:657)
at org.jboss.injection.JndiFieldInjector.inject(JndiFieldInjector.java:115)
... 49 more
I have tried a few things but, if anyone can point me in the right direction about this I would appreciate it.
It looks like the JNDI properties need to be set as if it were a remote client outside of the app server because of the ear isolation we have setup.
properties.put(Context.PROVIDER_URL, url);
InitialContext ctx = new InitialContext(properties);
Just specify the URL for the InitialContext and that should do the trick.