CXF WebService Call from Grails - web-services

I'm trying to call a WebService from Grails using CXF plugin version: 1.1.3
Have generated Java classes for the WSDL via the command:
WsdlToJava "--wsdl=src/java/wsdls/jdeRteListenerService.wsdl --mark -p mypackage.pms.OsrJdeRteSvc -client -impl"
When I went to run the webservice call I would get:
Class not known to this context for class: mypackage.pms.OsrJdeRteSvc.ListAllEventsRequest.
Following this stackoverflow article: JAXB Exception: Class not known to this context
I added to the Port class:
#XmlSeeAlso({mypackage.pms.OsrJdeRteSvc.impl.ObjectFactory.class, mypackage.pms.OsrJdeRteSvc.ListAllEventsRequest.class})
Now I get the error:
Unable to find a JAXB implementation to delegate.
JAXB Source has a comment:
if(!modified) {
// if the class list doesn't contain any of our classes,
// this ContextFactory shouldn't have been called in the first place
// if we simply continue, we'll just end up with the infinite recursion.
// the only case that I can think of where this could happen is
// when the user puts additional classes into the JAXB-generated
// package and pass them to JAXBContext.newInstance().
// Under normal use, this shouldn't happen.
// anyway, bail out now.
// if you hit this problem and wondering how to get around the problem,
// subscribe and send a note to users#jaxb.dev.java.net (http://jaxb.dev.java.net/)
throw new JAXBException("Unable to find a JAXB implementation to delegate");
}
https://svn.java.net/svn/jaxb~version2/tags/jaxb-2_2_3u1/xjc/src/com/sun/tools/xjc/runtime/JAXBContextFactory.java
I've subscribed to the list but not yet been approved.
Anyway, why am I getting: Unable to find JAXB implementation to delegate?

Related

How to bring SOAP capability to payara/micro in EJB project

I have an EJB project providing webservices (both SOAP and REST) running inside a container with payara/micro as base image, since payara/micro does not come with JAXWS(SOAP support) feature out of the box, however, by adding
cxf-rt-frontend-jaxws
and
cxf-rt-transports-http
as dependencies into the project as well as following this tutorial and put the following code instead:
#Override
public void loadBus(ServletConfig servletConfig) {
super.loadBus(servletConfig);
Bus bus = getBus();
BusFactory.setDefaultBus(bus);
Endpoint.publish("/MySoapService", new ASoapService());
}
I was able to make the SOAP interface almost available (wsdl information is publicly available already), and
http://localhost:8080/<my project name>/services
event listed out the available services as well their available methods and endpoints/WSDL/Target namespace information.
But when trying to access the SOAP service via SOAP client, I got on the server side errors with the following line of info:
...
Caused by: java.lang.NullPointerException: null
at com.example.ASoapService.getXxx
...
Where
ASoapService
Is Actually an EJB. So I tried instead to replace the above code with the following:
#EJB
ASoapService aSoapService
...
Endpoint.publish("/MySoapService", aSoapService);
During startup of container, I got
Caused by: javax.naming.NameNotFoundException: com.example.ASoapServiceF#com.example.ASoapService not found
By checking the logs, I found a possible reason:
When SOAP part starts up with the following code
Endpoint.publish("/MySoapService", aSoapService);
The EJB Container is not yet ready and thus the lookup of
ASoapService
failed, is such assumption correct? Because normally you should see something like:
[2018-02-02T14:43:57.821+0000] [] [INFO] [AS-EJB-00054] [javax.enterprise.ejb.container] [tid: _ThreadID=1 _ThreadName=main] [timeMillis: 1517582637821] [levelValue: 800] Portable JNDI names for EJB ASoapService: [java:global/<my project name>/ASoapService, java:global/<my project name>/ASoapService!com.example.ASoapService]
during start up, which is not the case for my situation.
I am relatively new to EJB and Glassfish world, can I somehow force EJB container to start first? Or does it actually have anything to do with the starting sequence? How to combine the two together?
Thanks in advance.
You shouldn't be trying to force EJB container to start. Instead, try one of the following:
instead of #EJB ASoapService aSoapService to inject the EJB try #Inject
ASoapService aSoapService - #Inject should wait for the dependencies therefore wait until the EJB is available
run the method Endpoint.publish from an object which is initialized after EJB container is ready, either from a startup singleton EJB or when CDI application scope is initialized: https://rmannibucau.wordpress.com/2015/03/10/cdi-and-startup/

"Method threw 'java.lang.LinkageError' exception" while calling a stub method

I am trying to call a method of a web service using an auto generated stub.
At following line it assigns,
Method threw 'java.lang.LinkageError' exception. Cannot evaluate org.apache.axiom.soap.impl.llom.soap11.SOAP11BodyImpl.toString()
as the SOAP envelope.
env = toEnvelope(getFactory(_operationClient.getOptions().getSoapVersionURI()),
simpleQueryInput587,
dummyWrappedType,
optimizeContent(new javax.xml.namespace.QName("http://docs.oasis-open.org/ns/bpel4people/ws-humantask/api/200803",
"simpleQuery")));
what is the reason for this?
This was caused since same package has been exported by two jars.

Symfony2: Mocked service is set in the container but not used by the controller (it still uses the original service)

I'm writing the functional tests for a controller.
It uses a class to import some data from third party websites and to do this I wrote a class that I use into Symfony setting it a service.
Now, in my functional tests, I want to substitute this service with a mocked one, set it in the container and use it in my functional tests.
So my code is the following:
// Mock the ImportDataManager and substitute it in the services container
$mockDataImportManager = $this->getMockBuilder('\AppBundle\Manager\DataImportManager')->disableOriginalConstructor()->getMock();
$client->getContainer()->set('shq.manager.DataImport', $mockDataImportManager);
$client->submit($form);
$crawler = $client->followRedirect();
As I know that between each request the client reboots the kernel and I have to set again the mocked class, I set the mock immediately before the calling to $client->submit.
But this approach seems not working for me and the controller still continue to use the real version of the service instead of the mocked one.
How can I use the mocked class to avoid to call the remote website during my functional test?
If I dump the set mocked service, I can see it is correctly set:
dump($client->getContainer()->get('shq.manager.DataImport'));die;
returns
.SetUpControllerTest.php on line 145:
Mock_DataImportManager_d2bab1e7 {#4807
-__phpunit_invocationMocker: null
-__phpunit_originalObject: null
-em: null
-remotes: null
-tokenGenerator: null
-passwordEncoder: null
-userManager: null
}
But it is not used during the $form->submit($form) call and, instead, is used the original service.
UPDATE
Continuing searching for a solution, I landed on this GitHub page from the Symfony project, where a user asks for a solution to my same problem.
The second call doesn't use the mocked/substituted version of his class, but, instead, the original one.
Is this the correct behavior? So, is it true that I cannot modify the service container on a second call to the client?
Yet, I don't understand why the service is not substituted in the container and I haven't a real solution to that problem.
Anyway I found some sort of workaround, in reality more correct as solution (also if it remains unclear why the service is not substituted and this is a curiosity I'd like to solve - maybe because the $client->submit() method uses the POST method?).
My workaround is a simple test double.
I create a new class in AppBundle/Tests/TestDouble and called it DataImportManagerTestDouble.php.
It contains the unique method used by the controller:
namespace AppBundle\Tests\TestDouble;
use AppBundle\Entity\User;
class DataImportManagerTestDouble
{
public function importData(User $user)
{
return true;
}
}
Then, I instantiate it in the config_test.yml (app/config/config_test.yml) file in the following way:
services:
shq.manager.DataImport:
class: AppBundle\Tests\TestDouble\DataImportManagerTestDouble
This way, during the tests, and only during the tests, the class loaded as service is the TestDouble and not the original one.
So the test pass and I'm (relatively) happy. For the moment, at least.

How to access EJB services from a grails standalone client

I've been having problems to access to my EJB services from a standalone client i've developed on grails 2.0.3. The EJB services are deployed on a glassfish server (Java). I tested this code on a netbeans tester class to access the EJBs:
Properties p = new Properties();
p.put("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
p.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
p.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
p.setProperty("org.omg.CORBA.ORBInitialHost", INTEGRATION_IP);
p.setProperty("org.omg.CORBA.ORBInitialPort", CORBA_PORT);
ctx = new InitialContext(p);
try {
this.admAuth = (AdmAuthenticationRemote) this.ctx.lookup(Tester.AUTHENTICATION_SERVICE_JNDI);
}catch(Exception e){
...
}
This Tester.AUTHENTICATION_SERVICE_JNDI is a variable tha contains the path to the deployed service, in this case something like "java:global/..." that represents the address to the service that is being requested. This way of accessing the services works perfectly from the tester, but when i try to do the same from grails doesn't works. I am able to create the context the same way, but when i invoke the ctx.lookup() call i get an exception:
Message: Lookup failed for 'java:global/...' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory,
java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming}
Cause: javax.naming.NamingException: Unable to acquire SerialContextProvider for SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.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 java.lang.RuntimeException: Orb initialization erorr]
The main exception is a naming exception, which means that it failed in the ctx.lookup(), but the cause is the orb initialization exception, which has another exception stack:
java.lang.RuntimeException: Orb initialization erorr
Caused by: java.lang.RuntimeException: java.lang.IllegalArgumentException: Can not set long field com.sun.corba.ee.impl.orb.ORBDataParserImpl.waitForResponseTimeout to java.lang.Integer
Caused by: java.lang.IllegalArgumentException: Can not set long field com.sun.corba.ee.impl.orb.ORBDataParserImpl.waitForResponseTimeout to java.lang.Integer
I'm really lost here. I've been having a lot of problems to get this going on grails, I had to get all glassfish jars (libs and modules) so it could make the InitialContext() call, but now i'm not sure if this is still a jar problem or a configuration problem or what it is.
I know that IllegalArgumentException occurs when u try to assign incompatible types in java, but i'm not setting anything like that, so i assume its an internal method initialization.
So the question is why is this exception coming up??
Is there another way to invoke my services from grails that works better??
The error is that you're trying to run your web application using the tomcat plugin in grails (using the command grails run-app). The problem is that when you try to create the InitialContext (com.sun.enterprise.naming.SerialInitContextFactory) groovy gives you an error casting some types if you're using the client libraries for GF 3.1. (I know that this is the problem, but I really don't know the reason for this. Because in theory this should work)
If you generate the .war file and you deploy in an AppServer, you can connect to your EJBs without problems. And if you deploy it on another GF server you don't have to import any of the client jars.
This will work perfect on production, the only problem is that you must compile and deploy your app on the GF server with every little change, and this is a bit annoying in development.
If you want to work outside of GF and using the command "grails run-app", you must modify two of the .jar GF 3.1 on your remote server, where you have the grails application:
1- The jar file $GLASSFISH_HOME/modules/glassfish-corba-omgapi.jar
You should search in the web the class com.sun.corba.ee.spi.orb.ParserImplBase, and modify this part
Field field = getAnyField(name);
field.setAccessible(true);
field.set(ParserImplBase.this, value);
for this
if (name.equalsIgnoreCase("waitForResponseTimeout")) {
Object newValue = new Long(1800000);
Field field = getAnyField(name);
field.setAccessible(true);
field.set(ParserImplBase.this, newValue);
} else {
Field field = getAnyField(name);
field.setAccessible(true);
field.set(ParserImplBase.this, value);
}
this should resolve the java.lang.IllegalArgumentException
2- The jar file $GLASSFISH_HOME/modules/glassfish-corba-orb.jar
you must delete the javax.rmi.CORBA.PortableRemoteObjectClass class of this library, because this class have conflicts with one used by the grails plugin
PS:
If you do not want to have the GF client jars in your grails application, you can add to the classpath of your client machine the following libraries
$GLASSFISH_HOME/modules/ejb-container.jar
$GLASSFISH_HOME/modules/ejb.security.jar
$GLASSFISH_HOME/modules/management-api.jar
If you use the grails console with the grails run-app command, must modify the configuration file $GRAILS_HOME/conf/groovy-starter.conf whit this
load $GLASSFISH_HOME/modules/ejb-container.jar
load $GLASSFISH_HOME/modules/ejb.security.jar
load $GLASSFISH_HOME/modules/management-api.jar

Creating webservice and client with JBossWS using Complex objects as arguments and return types

I am developing a WebService and Client for it using JBoss 5.1.0GA. The JBossWs stack was already preinstalled with the binary that I downloaded and as I understand it is JBossWs 3.1.2GA
I have developed a web service using this setup and have also created a client successfully. This is what I have.
A pojo web service deployed as a war file.
#WebService
public class Service{
#WebMethod
public CompleObj getConfiguration() {
CompleObj oConf = new CompleObj ();
for (int i = 0; i < 10; i++) {
NestObj oInst = new BOpRepoInstance("Val1", "Val2", "Val3", "Val4");
oConf.addRepoInstance(oInst);
}
return oConf;
}
}
Here,
CompleObj => is a Complex Object that has a list of type NestObj. Its
getter/setters, toString and some other methods.
NextObj => has 4 variables of Type String. Its getter/setters,
toString, hashCode, equals and some other methods.
Got this web service deployed successfully.
Later created a client using the eclipse wizard for generating Web Service Client using WSDL document. It also created a sample client file which would call the webservice and fetch the return value. This also worked like a charm.
Now my problem is, when eclipse generated stubs for clients it created classes for CompleObj and NestObj. These classes only has the variables and its getters/setters (this make sense as these are being generated from WSDL doc). Thus i loose a lot of other methods that includes toString, hasCode, equals etc, which I want to use at the Client side as well.
Now how can I make use of the actual class files defined in the WebService project directly and avoid the client to use the generated ones. I can provide the class files as .jar binary for the Client project, I cant really get how to achieve this.
Another question is, the web service location is embedded in the stubs directly, what can i do to have the webservice location passed as part of the argument to the invocation code?
The classes which are generated in the client side are just place
holders it is not deserilized version of your own classes,When you
invoke the service it is used to carry your object to server then
the JBOOSWS will do the JAXB mapping to the actual classes. So you
can not make the your own classes to be used in the client side
though they are look same.
URL will be fixed in the stub code, since in eclipse while generating WS client the first
thing you must provide is, the WSDL URL,then eclipse will generate the
client code accordingly,so generated code is specific to the WSDL
you provided. If you want to pass the WSDL dynamically,then you
need to have your own code to generate the client stubs by passed
WSDL URL using any WSDLtoJAVA or any other utility.