Using EJBs from a different JAR - ejb

I'm developing a JAX-WS WebService in JDeveloper 11.1.1.4 that should use EJBs from a JAR previously deployed to a WebLogic server. Both the WebService project and the EJB project are my own code, but I'd like to deploy them separately. For now I'm experimenting with the setup.
In the ExampleEJB project I have a bean ExampleBean that implements a remote interface Example.
#Remote
public interface Example {
public String doRemoteStuff();
}
#Stateless(name = "Example", mappedName = "ExampleApplication-ExampleEJB-Example")
public class ExampleBean implements Example {
public String doRemoteStuff() {
return "did remote stuff";
}
}
In that project, I have two deploy descriptors (ejb-jar.xml and weblogic-ejb-jar.xml):
ejb-jar.xml
<?xml version = '1.0' encoding = 'UTF-8'?>
<ejb-jar 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/ejb-jar_3_0.xsd"
version="3.0" xmlns="http://java.sun.com/xml/ns/javaee">
<enterprise-beans>
<session>
<ejb-name>Example</ejb-name>
</session>
</enterprise-beans>
</ejb-jar>
weblogic-ejb-jar.xml
<?xml version = '1.0' encoding = 'UTF-8'?>
<weblogic-ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-ejb-jar http://www.bea.com/ns/weblogic/weblogic-ejb-jar/1.0/weblogic-ejb-jar.xsd"
xmlns="http://www.bea.com/ns/weblogic/weblogic-ejb-jar">
<weblogic-enterprise-bean>
<ejb-name>Example</ejb-name>
<stateless-session-descriptor/>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>
Additionaly, I've created an EJB JAR deployment profile named example-ejb.jar and managed to deploy it to the server.
In the ExampleWS project I have an ExampleWebService:
#WebService(serviceName = "ExampleWebService")
public class ExampleWebService {
#EJB
Example example;
public String doStuff() {
return example.doRemoteStuff();
}
}
I added the ExampleEJB project dependency to this project (so it would compile). The only XML I have in this project is the web.xml used to describe the servlet. Also, I have the WebServices WAR file created automatically by jDeveloper when creating a WebService. Lastly, I created an EAR deployment profile named example-ws that only includes the WebServices WAR file in it's application assembly.
What do I need to do for this to work? Also, what would the procedure be if the ExampleEJB project was referenced from another project (say, AdditionalExampleEJB) that has additional beans that use ExampleBean? How would I reference the ExampleBean from there?
Thank you VERY MUCH for any help you can give me!
EDIT:
I've managed to reference the EJB from the WebService!
In the ExampleEJB project I modified the weblogic-ejb-jar.xml and now it looks like this:
weblogic-ejb-jar.xml
<?xml version = '1.0' encoding = 'UTF-8'?>
<weblogic-ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-ejb-jar http://www.bea.com/ns/weblogic/weblogic-ejb-jar/1.0/weblogic-ejb-jar.xsd"
xmlns="http://www.bea.com/ns/weblogic/weblogic-ejb-jar">
<weblogic-enterprise-bean>
<ejb-name>Example</ejb-name>
<stateless-session-descriptor>
<pool>
<max-beans-in-free-pool>10</max-beans-in-free-pool>
<initial-beans-in-free-pool>3</initial-beans-in-free-pool>
</pool>
<business-interface-jndi-name-map>
<business-remote>hr.example.Example</business-remote>
<jndi-name>ejb/example-ejb/Example</jndi-name>
</business-interface-jndi-name-map>
</stateless-session-descriptor>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>
In the ExampleWS project I added a deployment descriptor weblogic.xml that looks like this:
weblogic.xml
<?xml version = '1.0' encoding = 'UTF-8'?>
<weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-web-app http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"
xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
<ejb-reference-description>
<ejb-ref-name>ExampleReference</ejb-ref-name>
<jndi-name>ejb/example-ejb/Example</jndi-name>
</ejb-reference-description>
</weblogic-web-app>
Note that the ExampleReference value and ejb/example-ejb/Example value are something I decided to enter - I think they is more or less a developer's choice.
Also, I referenced the EJB in my WebService using the ExampleReference value, so my ExampleWebService looks like this:
ExampleWebService
#WebService(serviceName = "ExampleWebService")
public class ExampleWebService {
#EJB(
name="ExampleReference"
)
Example example;
public String doStuff() {
return example.doRemoteStuff();
}
}
Lastly, in the deployment profile of ExampleWS (the WebServices.war) I added the dependency contributor and checked the interface Example.class element (NOT the ExampleBean.java that has the implementation).
Now, how would this work if the Example bean was referenced from another EJB project (not a WebService)?

So, for all those that encounter the same problem, I have solved it. There is no way to look up a remote EJB in EJB 3.0 other than using InitialContext.lookup("jndi/name"). Also, narrowing the object seems to help in some ClassCastException situations, so I tend to do it as a precaution. This is how I look up my EJBs:
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
public Object lookup (String jndiName, Class type) throws NamingException {
return PortableRemoteObject.narrow(InitialContext.doLookup(jndiName), type);
}
If using EJB 3.1, there is a way using #EJB(lookup = "jndi/name"), but since I'm not using this version, I cannot guarantee that this works.

Related

Swagger not giving UI for Spring MVC Project

I am new to the Swagger and trying to implement it in the Spring MVC. I'm using latest dependency swagger-springmvc from http://mvnrepository.com/artifact/com.mangofactory/swagger-springmvc. So based on link https://dzone.com/articles/documenting-your-spring-api. I added following configuration in mvc-config.xml.
<!-- Serve static content - required for Swagger -->
<mvc:default-servlet-handler/>
<!-- to enable the default documentation controller-->
<context:component-scan base-package="com.mangofactory.swagger.controllers"/>
<!-- to pick up the bundled spring configuration-->
<context:component-scan base-package="com.mangofactory.swagger.configuration"/>
<!-- Direct static mappings -->
<mvc:resources mapping="*.html" location="/, classpath:/swagger-ui"/>
Also I used following from link shown above.
<bean class="com.xxx.xx.xx.SwaggerConfig"/>
Then I added
git clone https://github.com/wordnik/swagger-ui
cp -r swagger-ui/dist ~/dev/x-auth-security/src/main/webapps/docs
When I launch the site: http://localhost:8080/dp-rest/api-docs I don't see UI format, it only gives JSON format.
{"apiVersion":"1.0","swaggerVersion":"1.2","apis":[{"path":"/default/student-service","description":"Manage Student Service","position":0},{"path":"/default/student-service","description":"Manage Student Service","position":0}],"authorizations":[],"info":{"title":"Student API's","description":"API for Student ","termsOfServiceUrl":"terms.html","contact":"test#yahoo.com","license":"Commercial Proprietary","licenseUrl":"http://www.adbc.com"}}
Ny
#Configuration
#EnableSwagger
public class SwaggerConfig {
private SpringSwaggerConfig springSwaggerConfig;
#Autowired
public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) {
this.springSwaggerConfig = springSwaggerConfig;
}
#Bean
// Don't forget the #Bean annotation
public SwaggerSpringMvcPlugin customImplementation() {
return new SwaggerSpringMvcPlugin(this.springSwaggerConfig).apiInfo(
apiInfo()).includePatterns(".*");
}
private ApiInfo apiInfo() {
return new ApiInfo("Student API", "API for Student",
"term.html", "test#tahoo.com",
"Commercial Proprietary", "http://www.test.com");
}
}
Why UI format not coming when we launch the http://localhost:8080/sample-rest/api-docs site?
Then only I see raw JSON response not any ui, What is missing here? What I need to changed/add/modify my code?
According to the article you'll see a section that tells you where to find the documentation. I'm not sure if you're using spring-boot but...
After making these changes, I was able to open fire up the app with "mvn spring-boot:run" and view http://localhost:8080/docs/index.html in my browser.
In any case, swagger-springmvc is now called springfox and supports the latest swagger specification (2.0). There is also documentation available to help you get started. I would recommend using the latest version (2.3.1 as of this writing) of springfox instead.

How to make spring matrix variables work when request path template parameter is not the last in path and deploying to WebLogic 12.1.1?

I've been trying to use a matrix variable to provide additional information conceptually belonging to the request path parameter of a form "/path/{param}/someotherpath".
The application was configured to enable support for matrix variables (which is off by default).
However it still did not work out, so I created a simplified test case in the spring pitclinic sample application based on the sample code provided on the Spring MVC reference page:
#Controller
public class MatrixTestController
{
#RequestMapping(value = "/matrix/test/{petId}", method = RequestMethod.GET)
public String findPet(#PathVariable String petId,
#MatrixVariable(required=false, defaultValue="1") int q,
Model model) {
System.out.println("petId=" + petId + ", q=" + q);
model.addAttribute("petId", petId);
model.addAttribute("q", q);
return "matrixtest";
}
#RequestMapping(value = "/matrix/test/{petId}/paws", method = RequestMethod.GET)
public String findPet2(#PathVariable String petId,
#MatrixVariable(required=false, defaultValue="1") int q,
Model model) {
System.out.println("petId=" + petId + ", q=" + q);
model.addAttribute("petId", petId);
model.addAttribute("q", q);
return "matrixtest";
}
}
The requests to both methods succeeded for Tomcat (the value for q was properly overwritten from its default value):
http://localhost:8084/spring-petclinic/matrix/test/1;q=2
http://localhost:8084/spring-petclinic/matrix/test/1;q=2/paws
However, for WebLogic only the request to the first method succeeded:
http://localhost:7001/spring-petclinic/matrix/test/1;q=3
The request to the second one resulted in Error 404--Not Found page:
http://localhost:7001/spring-petclinic/matrix/test/1;q=2/paws
The second request mapping is the request mapping I would actually like to use in the real application.
The only thing I found so far that looks related to the problem (however is not related to Spring) is a page from 2011 (related to an older version of WebLogic):
http://cdivilly.wordpress.com/2011/04/22/java-servlets-uri-parameters/
which states:
Tomcat is the only container that understands that each segment of the path can have parameters. All the others assume the parameters can only appear on the last segment.
I did not find any information considering the use of matrix variables when deploying to WebLogic on the Spring MVC reference page (http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-matrix-variables).
I neither did find anything that looked related in the description of weblogic.xml deployment descriptor in regard to semicolons in the URLs.
Is there anything else I might overlook? Is there perhaps a Spring configuration parameter which needs to be additionally enabled for WebLogic?
The configuration
#Configuration
public class WebConfig extends DelegatingWebMvcConfiguration
{
#Bean
#Override
public RequestMappingHandlerMapping requestMappingHandlerMapping()
{
RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping();
handlerMapping.setRemoveSemicolonContent(false);
handlerMapping.setUseTrailingSlashMatch(false);
return handlerMapping;
}
#Bean
#Override
public RequestMappingHandlerAdapter requestMappingHandlerAdapter()
{
RequestMappingHandlerAdapter handlerApapter = super.requestMappingHandlerAdapter();
handlerApapter.setIgnoreDefaultModelOnRedirect(true);
return handlerApapter;
}
}
mvc-core-config.xml (just the change):
<!-- <mvc:annotation-driven conversion-service="conversionService"/>-->
<mvc:annotation-driven conversion-service="conversionService" enable-matrix-variables="true" />
<!-- Used to change configuration for RequestMappingHandlerMapping removeSemicolonContent property which is needed for matrix variables support: -->
<bean class="WebConfig"/>
weblogic.xml (to be able to deploy to WebLogic):
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app" 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 http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd">
<jsp-descriptor>
<keepgenerated>true</keepgenerated>
<debug>true</debug>
</jsp-descriptor>
<context-root>/spring-petclinic</context-root>
<container-descriptor>
<prefer-application-packages>
<package-name>antlr.*</package-name>
<package-name>org.hibernate.*</package-name>
<package-name>javax.persistence.*</package-name>
</prefer-application-packages>
</container-descriptor>
<dispatch-policy>
</weblogic-web-app>

Restful webservices(Apache wink+Guice+openjpa)

I would like to use the following technologies to develop restful webservice.
Apache wink+Guice3+openjpa. I dont know how to use guice with wink and openjpa. could you please explain.
I can't help you with OpenJPA, but I just now figured out how to use Guice with Wink. First of all, you do not need to use Guice's guice-servlet JAR as you would with a plain webapp. Just set up your webapp to use Wink as you normally would, then follow these steps.
Replace the wink-server JAR with the wink-guice-server JAR (available from the same source).
Change the servlet-class in your web.xml file from
org.apache.wink.server.internal.servlet.RestServlet
to
org.apache.wink.guice.server.internal.servlet.GuiceRestServlet
Also in web.xml, add this snippet to Wink's <servlet-class> element:
<init-param>
<param-name>deploymentConfiguration</param-name>
<param-value>com.yourco.yourproj.DeploymentConfiguration</param-value>
</init-param>
Finally, create a new Wink DeploymentConfiguration class, which I call here com.yourco.yourproj.DeploymentConfiguration.
package com.yourco.yourproj;
import com.google.inject.Module;
import org.apache.wink.guice.server.internal.GuiceDeploymentConfiguration;
import org.apache.wink.guice.server.internal.lifecycle.WinkGuiceModule;
public class DeploymentConfiguration extends GuiceDeploymentConfiguration {
#Override
public Module[] createModules() {
return new Module[] { new WinkGuiceModule(), new YourModule() };
}
}
YourModule is just a normal Guice module.

Weblogic could not find resource adapter with "correct" JNDI name for binding

I am trying to bind my message driven bean with Oracle JCA file adapter (which is included in the SOA suite) on Weblogic 10.3.5. So that my MDB can get notified when there is any .txt file is moved to specific directory.
After launching a Weblogic domain with SOA features supported, the file adapter is automatically deployed. On Weblogic console I can see the file adapter is deployed as a "Resource Adapter", health is "OK", state is "Active", as shown below:
Also I run the tests of the file adapter, and they all passed:
So I think the file adapter is correctly deployed and should be functional.
Then my message driven bean code looks like this:
import java.util.logging.Logger;
import javax.ejb.MessageDriven;
import javax.resource.ResourceException;
import javax.resource.cci.MessageListener;
import javax.resource.cci.Record;
#MessageDriven
public class FileAdapterClientMDB implements MessageListener {
private Logger logger = Logger.getLogger(FileAdapterClientMDB.class.getName());
public FileAdapterClientMDB() {
}
#Override
public Record onMessage(Record record) throws ResourceException {
logger.info("Received record: " + record);
return record;
}
}
Here are the content of my ejb-jar.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:ejb="http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd" version="3.0">
<display-name>MockEJB</display-name>
<enterprise-beans>
<message-driven>
<description>EMessage Driven Bean as File Adapter Client</description>
<display-name>FileAdapterClientMDB</display-name>
<ejb-name>FileAdapterClientMDB</ejb-name>
<ejb-class>com.test.FileAdapterClientMDB</ejb-class>
<messaging-type>javax.resource.cci.MessageListener</messaging-type>
<transaction-type>Container</transaction-type>
<activation-config>
<activation-config-property>
<activation-config-property-name>physicalDirectory</activation-config-property-name>
<activation-config-property-value>C:\dataDir</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>deleteFile</activation-config-property-name>
<activation-config-property-value>true</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>pollingFrequency</activation-config-property-name>
<activation-config-property-value>10</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>includeFiles</activation-config-property-name>
<activation-config-property-value>.*\.txt</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>minimumAge</activation-config-property-name>
<activation-config-property-value>0</activation-config-property-value>
</activation-config-property>
</activation-config>
</message-driven>
</enterprise-beans>
</ejb-jar>
And my weblogic-ejb-jar.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-ejb-jar xmlns:wls="http://www.bea.com/ns/weblogic/weblogic-ejb-jar" 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/ejb-jar_3_0.xsd http://www.bea.com/ns/weblogic/weblogic-ejb-jar http://www.bea.com/ns/weblogic/weblogic-ejb-jar/1.0/weblogic-ejb-jar.xsd">
<!--weblogic-version:10.3-->
<wls:weblogic-enterprise-bean>
<!--options:RESOURCE_ADAPTER_JNDI-->
<wls:ejb-name>FileAdapterClientMDB</wls:ejb-name>
<wls:message-driven-descriptor>
<wls:resource-adapter-jndi-name>eis/FileAdapter</wls:resource-adapter-jndi-name>
</wls:message-driven-descriptor>
<wls:jndi-name>FileAdapterClientMDB</wls:jndi-name>
<wls:local-jndi-name>FileAdapterClientMDB</wls:local-jndi-name>
</wls:weblogic-enterprise-bean>
</wls:weblogic-ejb-jar>
While deploying the EAR project, I got this message:
<20.4.2012 22:42:11 CEST> <Warning> <EJB> <BEA-010221> <The Message-Driven EJB:
FileAdapterClientMDB is unable to bind to the JCA resource adapter: eis/FileAdapter.
The Error was: No deployed ResourceAdapter with adapter JNDI name = 'eis/FileAdapter' was found.>
I have no idea why Weblogic complain this, since the "eis/FileAdapter" JNDI name is mentioned in the official user guide of the adapter. Also I can see it in Weblogic's JNDI tree:
What's more, when I run the code below in my testing web service:
try {
final Context context = new InitialContext();
final Object obj = context.lookup("eis/FileAdapter");
System.out.println("eis/FileAdapter => " + obj);
} catch (NamingException e) {
e.printStackTrace();
}
It prints out "eis/FileAdapter => oracle.tip.adapter.file.FileConnectionFactory#ff51dc", which means the JNDI name is correct!
So my question is, why Weblogic could not find resource adapter with a "correct" JNDI name for binding? Could someone give me some ideas on how to solve it?
as long as you don't see this warning repeating you have nothing to worry. It just shows that in the order of deployment when the MDB was getting deployed it could not get the adapter. Note an MDB keeps trying to connect every 5 secs so if the warning continues to fill the log then that means the MDB has not been able to get the adapter meaning its not working, if you saw the warning only once you can safely ignore it or change the order of deployment and push the MDB little later.

Strange problem with SEAM stateful session bean

I've got a stateful session bean.
#Scope(ScopeType.SESSION)
#Name("chuckNorrisBean")
public class ChuckNorrisBean implements Serializable, ChuckNorris
with some function
public void roundHouseKick()
{
...
}
interface
#Local
public interface ChuckNorris
{
public void roundHouseKick()
{
...
}
}
and calling them on a jsf .xhtml page using
#{chuckNorrisBean.roundHouseKick}
which works perfectly fine. However if I add the #Stateful annotation to the bean so it becomes
#Stateful
#Scope(ScopeType.SESSION)
#Name("chuckNorrisBean")
public class ChuckNorrisBean implements Serializable, ChuckNorris
and the page will load with exceptions complainig about
Exception during request processing:Caused by javax.servlet.ServletException
with message: "#{chuckNorrisBean.roundHouseKick}: javax.el.MethodNotFoundException:
//localhost/universe/earth.xhtml #41,65 action=
"#{chuckNorrisBean.roundHouseKick}": Method not found:
ChuckNorrisBean:a6gkg-w6das4-g8wmgh0y-1-g8woy0wo-4b.roundHouseKick()"
Any advice on what might've went wrong with my chuckNorrisBean?
The system is built on SEAM/richfaces.
Thanks!
---- Edited to add more info ----
The project is built with maven 2.1 packaged as ear (a single .ear file as target output).
The application server is JBoss.
After more debugging and fiddling, putting
<page view-id="/index.xhtml">
<action execute="#{chuckNorrisBean.roundHouseKick}" />
</page>
in pages.xml seems to do the kicking just fine. I still couldn't figure out why calling it on a page did not work.
That is quite strange.
Have you tried
#{chuckNorrisBean.roundHouseKick()}
instead of
#{chuckNorrisBean.roundHouseKick}
Just to see what happens

Resources