EJB as WebService in Enterprise Application Project - java

i have created an Maven Enterprise Application Project in Netbeans. I have created an example-EJB, a Remote and a local interface. Now i want to publish a SOAP webservice by using these EJB, but there is something i'm doing wrong, because in glassfish i can't view the endpoint (with wsdl etc.). But it is listed as a component:
Component Name: RecommendationSOAPService, SHITSTORMRECOMMENDER
Module Name: ShitstormRecommender-ejb-1.0.jar, ShitstormRecommender-ejb-1.0.jar
Type: StatelessSessionBean, StatelessSessionBean
My EJB:
import com.sun.javafx.scene.control.skin.VirtualFlow;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import org.andy.dto.Recommendation;
import org.andy.dto.RecommendationRequest;
#Stateless(name = "SHITSTORMRECOMMENDER")
public class ShitstormRecommenderEJB implements ShitstormReommenderEJBRemote,
ShitstormRecommenderEJBLocal {
#Override
public List<Recommendation> getRecommendation(RecommendationRequest request) {
Recommendation r1 = new Recommendation("Task 2", 10, "blubb");
Recommendation r2 = new Recommendation("Task 1", 5, "bla");
List<Recommendation> recommendations = new ArrayList<>();
recommendations.add(r1);
recommendations.add(r2);
return recommendations;
}
}
My Remote Interface (Local interface looks like the same only with #local):
#Remote
public interface ShitstormReommenderEJBRemote {
public List<Recommendation> getRecommendation(RecommendationRequest request);
}
My WebService-Class (located in the ejb-Container with the interfaces and the EJB):
package org.andy.service;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import org.andy.dto.Recommendation;
import org.andy.dto.RecommendationRequest;
import org.andy.ejb.ShitstormReommenderEJBRemote;
#WebService(
name= "ShitstormRecommender",
portName = "ShitstormRecommenderPort",
serviceName = "ShitstormRecommenderService",
targetNamespace = "http://shitstormRecommendation.org"
)
#Stateless
public class RecommendationSOAPService{
#EJB
private ShitstormReommenderEJBRemote recommender;
#WebMethod
public String sayCiao(){
return "ciao";
}
#WebMethod
#WebResult(name="recommendations")
public List<Recommendation> getRecommendation(
#WebParam(name="recommendationRequest") RecommendationRequest request) {
return recommender.getRecommendation(request);
}
}
Maybe you can say, what i have to do to bring it to work? I have tried it out from this tutorial. There it seems to be working, but i think i have forgot something.
Thanks a lot for your help!

Related

Integration testing for events in the Jersey container listener

I have an application based on Jersey JAX-RS. I need to refactor the event handler and therefore also write a test for it.
I'm trying to do this with the JerseyTest Framework. I created a configuration to extend ResourceConfig, but when I use the target () call the handler is not called.
I will present the situation using code.
Here is an example Resource class:
package com.my.page;
import org.glassfish.hk2.api.messaging.Topic;
import com.my.core.entity.Link;
import com.my.core.location.LinkHitLocationFactory;
import com.my.core.service.LinkService;
import com.my.core.service.link.LinkFinder;
import com.my.core.service.link.LinkFinderFactory;
import com.my.event.LinkHitEvent;
import com.my.exception.FragmentNotFoundException;
import javax.annotation.security.PermitAll;
import javax.inject.Inject;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
#PermitAll
#Path("/")
public class LinkResource {
#Inject
private LinkService linkService;
#Inject
private Topic<LinkHitEvent> linkHitPublisher;
#Inject
private LinkFinderFactory linkFinderFactory;
#Inject
private LinkHitLocationFactory linkHitLocationFactory;
#GET
#Path("/{fragment:[^ ]{1,32}}")
public Response redirect(
#PathParam("fragment") String fragment,
#HeaderParam("Range") String range,
#HeaderParam("User-Agent") String userAgent,
#Context HttpHeaders headers) throws Exception {
LinkFinder linkFinder = linkFinderFactory.getLinkFinder(fragment);
Link link = linkFinder.getLink(fragment);
if (link.isExpired()) {
throw new FragmentNotFoundException(fragment);
}
linkService.insertHit();
linkHitPublisher.publish(new LinkHitEvent(link));
return handlerFactory.getHandler(link).handleGet(link, range).build();
}
}
Event test:
package com.my.page;
import org.glassfish.hk2.extras.events.internal.TopicDistributionModule;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import pl.comvision.hk2.events.ThreadedEventDistributorService;
import com.my.client.CallbackTargetBuilder;
import com.my.core.entity.Link;
import com.my.core.mapper.LinkMapper;
import com.my.core.service.LinkService;
import com.my.page.resource.LinkResource;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;
import static javax.ws.rs.core.Response.Status.TEMPORARY_REDIRECT;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
#RunWith(MockitoJUnitRunner.class)
public class CallbackEventTest extends JerseyTest {
#Mock
private LinkMapper linkMapper;
#Mock
private LinkService linkService;
private CallbackTargetBuilder callbackTargetBuilder;
private final String callbackUrl = "";
#Override
protected Application configure() {
this.callbackTargetBuilder = spy(new CallbackTargetBuilder(this.callbackUrl));
ResourceConfig config = new ResourceConfig(LinkResource.class);
config.register(new TopicDistributionModule());
config.register(new AbstractBinder() {
#Override
protected void configure() {
addActiveDescriptor(ThreadedEventDistributorService.class).setRanking(100);
}
});
config.register(new EventsContainerListener(CallbackEventHandler.class));
config.register(new AbstractBinder() {
#Override
protected void configure() {
bind(linkMapper).to(LinkMapper.class);
bind(linkService).to(LinkService.class);
bind(mock(LinkService.class)).to(LinkService.class);
bind("").to(String.class).named("varPath");
bind("127.0.0.1").to(String.class).named("requestIP");
bind(callbackTargetBuilder).to(CallbackTargetBuilder.class);
}
});
return config;
}
#Test
public void publish_event() {
Link link = mock(Link.class);
when(link.getUrl()).thenReturn("example");
when(link.getName()).thenReturn("test");
when(linkMapper.getByName(anyString())).thenReturn(link);
Response response = target("/testY").property("jersey.config.client.followRedirects", false).request().get();
assertEquals(TEMPORARY_REDIRECT.getStatusCode(), response.getStatus());
verify(callbackTargetBuilder).build();
}
}
For testing purposes, I only injected callbackTargetBuilder into the handler, and called the build method on it to verify the call:
package com.my.page;
import org.glassfish.hk2.api.messaging.MessageReceiver;
import org.glassfish.hk2.api.messaging.SubscribeTo;
import org.jvnet.hk2.annotations.Service;
import com.my.client.CallbackTargetBuilder;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
#Service
#Singleton
#MessageReceiver
public class CallbackEventHandler {
#Named("callbackUrl")
private String url;
#Inject
private CallbackTargetBuilder callbackTargetBuilder;
#MessageReceiver
public void handle(#SubscribeTo LinkHitEvent event) {
Form form = new Form();
form.param("id", event.getLink().getId().toString());
form.param("name", event.getLink().getName());
callbackTargetBuilder.build();
Client client = ClientBuilder.newClient();
client.target(url).request().post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
}
}
Edit:
I tried to register dependencies differently, but it does not bring satisfactory results. Each time verification fails:
verify (callbackTargetBuilder) .build ();
Looking for information I found that I can configure the DeploymentContext, but I don't know if this is the right direction.
Edit the second:
A quick test shows that I may have some more basic problem with mocking. Because the call:
verify (linkService) .insertHit (anyObject ());
It also fails.
I will write only for posterity that the above code is correct. The problem was a lot of small bugs in the tested code and how to mock it.

Spring: GCP and JPA - Missing EntityManagerFactory

I have a working implementation of Spring Boot with Tomcat that handles fine in a JAR file within a Linux environment. The same code fails to work with Google Cloud. I'm trying to get JPA to work.
Google Cloud prefers Jetty over Tomcat. This may relate to my issue, but I'm not sure how to fix it. I have the default recommended conversion from a standard Spring Boot JAR to a WAR version for Google Cloud's AppEngine. My dependencies work fine if I try them in a pre-set project from the spring.io site. I'm not using databases, so I cut out MySQL, which is default.
My problem relates to a missing EntityManagerFactory. Since I'm trying to keep this post brief, I just include what I think is vital. You can find the essentials to the complete project at: https://github.com/shatterblast/spring-sylveria_fix-search
Basically, I can't bring up the Admin Console for this GCP project. The project and the Admin Console both respond with a 503 from a request. There is no error message during startup, and it executes fine. From tweaking the code, I found the EntityManager bean as the problem itself. Re-naming beans has not helped.
Thank you.
import com.weslange.springboot.sylveria.entity.Gamer;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
#Repository
public class GamerDAOHibernateImpl implements GamerDAO {
private EntityManager entityManager;
#Autowired
public GamerDAOHibernateImpl( EntityManager theEntityManager ) {
entityManager = theEntityManager;
}
#Override
public Gamer findById( int id ) {
Session currentSession = entityManager.unwrap( Session.class );
Gamer gamer = currentSession.get( Gamer.class, id );
return gamer;
}
#Override
public void save( Gamer gamer ) {
Session currentSession = entityManager.unwrap( Session.class );
currentSession.saveOrUpdate( gamer );
}
}
.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
#Repository
public class TokenDAOHibernateImpl implements TokenDAO {
private EntityManager entityManager;
#Autowired
public TokenDAOHibernateImpl(EntityManager theEntityManager) {
entityManager = theEntityManager;
}
}
.
import com.weslange.springboot.sylveria.SylveriaServerApplication;
import com.weslange.springboot.sylveria.entity.Token;
import com.weslange.springboot.sylveria.service.GamerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
#RestController
#RequestMapping( "/" )
public class TokenRestController {
private static final Logger logger = LoggerFactory.getLogger( SylveriaServerApplication.class );
private GamerService gamerService;
#Autowired
public TokenRestController( GamerService gamerService ) {
gamerService = gamerService;
}
#PostMapping( "/" )
public HashMap addEmployee( #RequestBody Token token, HttpServletRequest request ) {
HashMap<String, String> returnMap = new HashMap();
returnMap.put( "sylveriaConnectionSuccess", "true" );
return returnMap;
}
}

Extending and customizing existing REST API

I wanted to extend or customize my existing rest apis. In my rest the Service calls the Handler which is supposed to contain business logic (as a product) and I need a way to extend or customize this (per client customization). Please advise how to go about doing this. Attached is a simple hello world setup I have, it would be great it a hook into this 'DefaultGreetingsHandler.greetUser' can be shown.
package com.myapi.greetings.rest;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.myapi.greetings.handler.GreetingsHandler;
import com.myapi.greetings.model.Greeting;
#Path("/greetings")
public class GreetingsService {
#Inject
GreetingsHandler handler;
#GET
#Path("/{name}")
public Response getCustomMessage(#PathParam("name") String name) {
String output = handler.greetUser(name);
return Response.status(200).entity(output).build();
}
}
I need a hook in the Handler.greetUser to be able to customize per client
package com.myapi.greetings.handler;
import javax.inject.Inject;
import com.myapi.greetings.dao.GreetingsDao;
public class DefaultGreetingsHandler implements GreetingsHandler {
#Inject
GreetingsDao dao;
#Override
public String greetUser(String name) {
return dao.getGreeting() + name;
}
}
Its a simple maven based rest project in java. Please refer to following link for the complete setup zip file.
https://1drv.ms/u/s!AulFHVWnSJeFaqIB0JHKzo95DbU
Appreciate the help.
Create a New Class MyApplicationBinder
import org.glassfish.hk2.utilities.binding.AbstractBinder;
public class MyApplicationBinder extends AbstractBinder {
#Override
protected void configure() {
bind(GreetingsHandler.class).to(GreetingsHandler.class);
}
}
and then Register it in the main application class
#ApplicationPath("webapi")
public class MyApp extends ResourceConfig{
public MyApp() {
register(new MyApplicationBinder());
packages(true, "com.myapi.greetings.rest");
}
}
This should make your application work .

Cannot bind a ContainerRequestFilter using Glassfish4 and JAX-RS

I am having trouble attaching a ContainerRequstFilter to a very simple JAX-RS rest application inside Glassfish4.
I believe that I've followed the instructions from both the javadoc and various other tutorial sources, but I am now at a complete loss.
The entire source (very short) is below, with the expected functionality:
(login) A user can log in at http://localhost/app/api/login/uname/password and the response is "You are logged in, uname"
(verify) User visits http://localhost/app/api/login/verify/uname and the response is a 401 unauthorized.
The second bit is meant the be implemented as a filter. What actually happens is that the first bit (login) works, and the second bit (verify) completely ignores the filter (including nothing in the logs to indicate that the filter ran). That is, the output is just "Every thing is fine, uname", rather than a 401 error.
What I want to understand is the way to get the filter attached to the verify action. For reference
I'm running glassfish 4.1 build 13
I'm compiling and deploying using gradle, with the deployment action
assassin deploy --force --contextroot /app /path/to/app.war
Glassfish reports that it's using Jersey 2.10.4
Here is the entirety of the source related to the application:
RestApp.java
package test.pack;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/api")
public class RestApp extends Application
{
#Override
public Set<Class<?>> getClasses()
{
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(Login.class);
return classes;
}
}
Login.java
package test.pack;
import javax.ejb.Stateless;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
#Stateless
#Path("login/")
#Produces("text/json")
public class Login
{
#GET
#Path("{username}/{password}")
public Response login(#PathParam("username") String username, #PathParam("password") String password)
{
System.out.println("Logging in");
return Response.ok("You are logged in, " + username).build();
}
#GET
#Path("/verify/{username}")
#Secured
public Response verify(#PathParam("username") String username)
{
System.out.println("Verify");
return Response.ok("Everything is fine, " + username).build();
}
Secured.java
package test.pack;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.ws.rs.NameBinding;
#NameBinding
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE, ElementType.METHOD})
public #interface Secured
{
}
LoggedInFilter.java
package test.pack;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Response;
#Secured
public class LoggedInFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
System.out.println("request");
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
}
Ugh. That's embarrassing.
The next tutorial I visited had the solution, which was to register the filter in the RestApp class.
RestApp.java
#ApplicationPath("/api")
public class RestApp extends Application
{
#Override
public Set<Class<?>> getClasses()
{
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(Login.class);
return classes;
}
#Override
public Set<Object> getSingletons()
{
Set<Object> singletons = new HashSet<Object>();
singletons.add(new LoggedInFilter());
return singletons;
}
}
I'll leave the answer here rather than deleting the question, since it was only in one of 4 tutorials that I read, and so this might be at least a little interesting.

How to get or know wsdl of a deployed web service from tomcat?

I am learning SOAP/WebService and I have created a project to start with. The project structure is :
I created a WAR and deployed to apache-tomee-plume-1.7.1, but the problem is that how to get WSDL address of the WebService.
The code of the file ProductWS.java is :
package org.mano.ws;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.jws.WebService;
import org.mano.ejb.ProductEJB;
import org.mano.entity.Product;
#WebService
public class ProductWS {
#EJB
ProductEJB productEJB;
public List<Product> getAllProductDetails(){
return productEJB.getAllProducts();
}
public List<String> getAllProductNames(){
List<Product> list=productEJB.getAllProducts();
List<String> productNames = new ArrayList<>();
for(Product p:list){
productNames.add(p.getName());
}
return productNames;
}
}
And Product.java is a POJO class.
Please suggest..

Categories

Resources