I have a problem when i want to expose my EJB Project as JAX-RS service. I've tried to find a solution many times but i've not fixed it. I've succeeded deploy my application but i didn't found my rest service in localhost:4848 => Applications => My_Application. Normally, if a rest service is deployed, there is "Launch" button.
I use glassfish4 and eclipse Java EE.
My EJB Project is like that:
Package ejb: TestSessionBean.java
Package rest: RestTest.java and RestTestApp.java
TestSessionBean.java
#Path("/peter")
#Stateless
#LocalBean
public class TestSessionBean {
public TestSessionBean() {
// TODO Auto-generated constructor stub
}
#GET
public String sayHello() {
return "Hello";
}
}
RestTest.java
#Path("/ep")
public class RestTest {
#GET
public String sayBonjour() {
return "Bonjour";
}
}
RestTestApp.java
#ApplicationPath("/test/*")
public class RestTestApp extends Application {
}
I also tried to config my project: Properties => Project Facets => enable JAX-RS (but when i clicked on "Further configuration available", i had "Type: Disable Library Configuration".
I tried localhost:8080/ejbtest/test/peter/ and localhost:8080/ejbtest/test/ep but both didn't work.
But if i create a new Dynamic Web Project all and copy all of my source files in ejbtest into this project. It works! So i think about something to do in eclipse configuration of ejb project. Any solution?
Thank you in advanced.
Related
I'm trying to run my web application based on javax.mvc, but I get 404 error. I think there should be an issue related to the application path, but I don't know exactly what's wrong.
XAMPP is installed and IntelliJ idea is configured to run tomcat7 as the web server.
Application code:
#ApplicationPath("web")
public class StoreApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> set = new HashSet<>();
set.add(ProductController.class);
return set;
}
}
Controller:
#Controller
#Path("products")
public class ProductController {
#Inject
private Models models;
#GET
public String list() {
models.put("products", Product.list());
System.out.println("helllo");
return "/WEB-INF/jsp/list.jsp";
}
}
This is a maven project. The build process is done with IntelliJ idea default settings.
Base url is set in StoreApplication.java as web with application path.
The war url is http://localhost:8080/elearning_war/ as depicted in the picture.
And the controller path is products. So I expect to show a list of products in http://localhost:8080/elearning_war/web/products, but instead, I get a 404 error page.
In my opinion, because of #ApplicationPath("web") the URL should be http://localhost:8080/web/products.
I'm using Eclipse with Glassfish for my first steps in Java EE. I've created three eclipse projects (JPA project, EJB project, Web project). I've created a local EJB bean TestBean with a local interface TestBeanLocal:
#Stateless
#LocalBean
class TestBean implements TestBeanLocal {
#Override
public void doSomething(List<JPAEntity> myEntities) {
for(JPAEntity a : myEntities) {
}
}
}
and a ManagedBean that uses the EJB:
#MangagedBean
public class MyBean {
#EJB
private TestBeanLocal testBean;
#PostConstruct
private void init() {
//load JPAEntity from Database
List<JPAEntity> myEntities = ....
testBean.doSomething(myEntities);
}
}
My problem is that I get a ClassCastException at the for loop in the TestBean.
java.lang.ClassCastException: us.mypackage.jpa.JPAEntity cannot be cast to us.mypackage.jpa.JPAEntity
I found another stackoverflow question that says that this error message is because of two different classloaders. How can I fix this? Can I tell EJB to use the same classloader that my webproject uses?
It seems that the entity jar is located in both war and ear
Try to remove the entity jar from the war library
War should see the ear libraries file
HTH
Steps to reproduce:
Create ejb project. (For example: Project1)
Create annotation class (For example: Test.class):
#Retention(RetentionPolicy.RUNTIME)
public #interface Test {
}
Create a simple java project. (For example: Project2)
Add Project1 as an ejb dependency to Project2.
Create simple class (For example: TestModel) and apply #Test annotation to it:
#Test
public class TestModel {
...
}
Create ear project. (For example: Project3)
Create ejb-module in Project3. (For example: Project3-ejb)
Add Project2 as a jar dependency to Project3-ejb.
Create stateless timer in Project3-ejb:
#Stateless
#LocalBean
public class Timer {
#Schedule(minute = "*", second = "*", hour = "*")
public void myTimer() {
try {
System.out.println(TestModel.class.getAnnotations().length);
} catch (SecurityException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
}
Clean, build and deploy Project3 to glassfish 3 or 4.
In server output you will see 0. Why?
I found that this problem is specific only for glassfish servers. If I deploy Project3 to Jboss server, I will see 1 in the server output. Seems, this is glassfish bug. I created ticket: https://java.net/jira/browse/GLASSFISH-20990
Also, if in step 4 add Project1 as jar dependency, I see 1 in server output.
I'm writing custom JAX-RS 2.0 application (under Jersey 2.3.1) which holds some data for use by all the resources.
public class WebApp extends org.glassfish.jersey.server.ResourceConfig {
public WebApp() {
packages("my.resources.package");
}
}
(I could use API's javax.ws.rs.core.Application as well, the described result is the same)
Then I inject the object into a resource
#Path("test")
public class Test {
#Context
Application app;
#GET
#Path("test")
public String test() {
return "Application class: " + app.getClass();
}
}
However, the result of a call is
Application class: class org.glassfish.jersey.server.ResourceConfig$WrappingResourceConfig
which makes me use some ugly tricks like
if (app instanceof WebApp) {
return (WebApp) app;
} else if (app instanceof ResourceConfig) {
return (WebApp) ((ResourceConfig) app).getApplication();
}
My understanding of JAX-RS 2.0 spec section 9.2.1:
The instance of the application-supplied Application subclass can be injected into a class field or method parameter using the #Context annotation. Access to the Application subclass instance allows configuration information to be centralized in that class. Note that this cannot be injected into the Application subclass itself since this would create a circular dependency.
is that application-supplied Application subclass is mine WebApp, not JAX-RS implementation-specific wrapper.
Also, changing this fragment
#Context
Application app;
to this
#Context
WebApp app;
causes app to be null, due to ClassCastException during context injection, so the declared type doesn't matter.
Is it a bug in Jersey or my misunderstanding?
UPDATE: I checked the behaviour under RESTEasy 3.0. The injected object is my WebApp, without any wrappers. I'd call it a bug in Jersey.
This doesn't seem like a bug. According to JAX-RS 2.0 spec you can inject Application into your resource classes (for example) but it does not say anything about directly injecting custom extensions of the Application. Not sure what your use-case is but you can register custom HK2 binder that will allow you to inject directly WebApp into resources:
public class WebApp extends org.glassfish.jersey.server.ResourceConfig {
public WebApp() {
packages("my.resources.package");
register(new org.glassfish.hk2.utilities.binding.AbstractBinder() {
#Override
protected void configure() {
bind(WebApp.this);
}
});
}
}
I too have encountered this using Jersey 2.4.1.
FWIW: I agree it seems like a bug according to the spec para 8.2.1. The statement "The instance of the application-supplied Application subclass" seems perfectly clear.
I have an alternative workaround that doesn't involve glassfish.hk2 but still concentrates the Jersey-specific code in the Application-derived class.
public class MyApp extends ResourceConfig {
...
static MyApp getInstance( Application application) {
try {
// for a conformant implementation
return (MyApp) application;
} catch (ClassCastException e) {
// Jersey 2.4.1 workaround
ResourceConfig rc = (ResourceConfig) application;
return (MyApp) rc.getApplication();
}
}
...
}
public class MyResource {
...
#Context Application application;
...
SomeMethod() {
... MyApp.getInstance( application);
}
}
Hope this is useful.
This appears to be fixed in a later version og Jersey. The same approach works for me with Jersey 2.16 at least. My injected Application object is of the correct subclass without any wrapping whatsoever.
Edit: Or maybe the version is irrelevant after all. Please see the comments to this answer.
I have webproject on Java EE 5 and Websphere 7.0
I need to create scheduler and start it after deploy application.
What I tried:
I create EJB with interface:
#Local
public interface ISchedulerBean {
public void executeTimer(Timer timer);
public void createTimer();
}
stateless session bean implements this interface. Method createTimer creates timer instance from TimerService. This part of code work fine.
Also I need to call method createTimer() after application deploy.
I tried:
Add listener servletContext:
public class SchedulerInitialiserContextListener implements ServletContextListener {
//service to lookup ejb
private WebServiceLocator webServiceLocator;
private SchedulerService schedulerService;
public SchedulerInitialiserContextListener() {
webServiceLocator = new WebServiceLocator();
schedulerService = webServiceLocator.getSchedulerService();
}
public void contextDestroyed(ServletContextEvent ctx) {
}
public void contextInitialized(ServletContextEvent ctx) {
schedulerService.createTimer();
}
}
create Servlet with 1 where inject SchedulerBean in init() method and call createTimer.
But this does not work, because at first webspere deploy web application, call listeners, initialize servlets, and only then deploy ejb.jar in which all ejb are located. I can see that in webshpere log file. So when I try get ejb throw #EJB annotation or lookup I get Exception, beacause ejb has not been found.
May be is other approach to start timer after deploy ejb module or change deploy order?
You can set the startup order of your modules.
Assuming you develop with Rational Application Developer do the following:
Right click your ear project and click Java EE -> Open WebSphere Application Server Deployment.
Look for the Application section, you will see all the modules and you can set the Start weight for each one.
Make sure your web project containing the Context Listener has the largest value an you should be fine.
This operation creates an ibmconfig directory under your ear project's META-INF, make sure you package it in your build process