I am deploying JAVA EE application in WildFly 8.1.0 Final. After deployments its replaces address in SOAP address location to Remote Interface rather than to Stateless EJB WebService.
E.g,
#Remote
public interface SbbAccess {
...
}
#WebService(name="SbbAccess", serviceName="pfmjainslee11_diagram", targetNamespace="http://jee.v1.sbb.profile" )
#Addressing
#HandlerChain(file = "jaxws-handlers.xml")
#TransactionManagement(TransactionManagementType.BEAN)
public #Stateless class SbbAccessBean implements SbbAccess {
...
}
WSDL available from wildlfy is
<wsdl:port binding="tns:pfmjainslee11_diagramSoapBinding" name="SbbAccessPort">
<soap:address location="http://linus:8080/sbb---v1.EJB/pfmjainslee11_diagram/SbbAccess"/>
</wsdl:port>
this should have been like
<wsdl:port binding="tns:pfmjainslee11_diagramSoapBinding" name="SbbAccessPort">
<soap:address location="http://linus:8080/sbb---v1.EJB/pfmjainslee11_diagram/SbbAccessBean"/>
</wsdl:port>
Any suggestion what is causing this behavior?
Regards,
That's the expected behaviour as a result of at least two of the following :
Your SLSB implements an #Remote interface
It's recommended by the specification that the interface name is mandatory in the JNDI lookup naming, when the SLSB implements a business interface.
The SLSB is being accessed remotely
The naming lookup options are:
[/application name]/module name/enterprise bean name[/interface name]
In theory, you're not required to implement #Remote, so if it's causing you any discomfort, you could remove the interface implementation and you'll be fine
Related
I am currently fronting issues mixing a CXF web service with Spring #Configurable annotation.
From one side I have my CXF web service fully working and configured like this :
<import resource="classpath:some-other-context.xml" />
<jaxws:server id="Init"
serviceClass="package.to.my.ServiceInterface"
address="/">
<jaxws:serviceBean>
<bean class="package.to.my.BADematInitImpl">
</bean>
</jaxws:serviceBean>
</jaxws:server>
<context:spring-configured />
And in my some-other-context.xml is my Spring configuration containing the following Bean's :
#Configurable(autowire = Autowire.BY_TYPE)
public class MyConfigurable {
#Autowired(required=true)
private A a;
#Autowired(required=true)
private B b;
#Autowired(required=true)
private C c;
...
}
But when I try to create a new instance of MyConfigurable bean into my service, I get a NullPointerException due to the null valued supposed-autowired A,B and C objects.
Any idea ?
#Configurable is a marker used by the AOP load-time-weaving stuff. I assume you are not using any AOP, because there is nothing mentioned about it in your question. Second thing: you don't have to use required=true in your #Autowired annotation as true is the default value of required. I would suggest you to change your code like this:
Add these to elements in your spring configuration file:
<context:component-scan base-package="your.pckg.toscan"/>
Documentation says:
Scans the classpath for annotated components that will be
auto-registered as Spring beans. By default, the Spring-provided
#Component, #Repository, #Service, and #Controller stereotypes will
be detected.
<context:annotation-config/>
Documentation says:
Activates various annotations to be detected in bean classes: Spring's
#Required and #Autowired, as well as JSR 250's #PostConstruct,
#PreDestroy and #Resource (if available), JAX-WS's #WebServiceRef (if
available), EJB3's #EJB (if available), and JPA's #PersistenceContext
and #PersistenceUnit (if available). Alternatively, you may choose to
activate the individual BeanPostProcessors for those annotations.
So changing your code to:
#Component
public class MyConfigurable {
#Autowired
private A a;
#Autowired
private B b;
#Autowired
private C c;
...
}
Everything should work just fine.
I finally found out the problem.
I needed to add this configuration into my third-part application XML files :
<context:load-time-weaver/>
... and add this argument to my jvm launch command line :
-javaagent:"path\to\my\spring-agent.jar"
And it just works like a charm.
I understand that this is because Spring needs at some point to have an entity managing its AOP part so that the dependencies are well injected. It would be interesting if someone had further explanations.
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.
I'm currently learning the new Java EE 6 component models and am confused with the latest dependency injection mechanism. So here are my questions:
1) What is the difference between #Inject and #EJB
2) If I have a simple POJO that contains another POJOs (which one of them is the DAO code), what would be the better choice: #Inject or #EJB?
Can I mix #Inject and #EJB?
An example would be:
ClassA implements InterfaceA and has
an instance of ClassA_Adaptor
ClassA_Adaptor implements InterfaceAB
and has an instance of ClassB
ClassB implements InterfaceB and has
an instance of ClassB_Adaptor and an
instance DAO_ClassB
ClassB_Adaptor implements InterfaceB
and has an instance of ClassC
ClassC implements InterfaceBC and has
an instance of WebService_ClassC
DAO_ClassB will use JPA 2.0
(#PersistenceContext)
I'd like to inject all of them including the DAO and the WebService.
3) Is it a bad approach to only use transactional for certain operations but not for all?
As an example: Some methods in DAO_ClassB are your typical query, while other methods are "write" methods. Is it bad to not wrap the "READ" methods with transaction?
To my understanding, the DAO_ClassB can be wrapped with transaction using #EJB (inject the DAO_ClassB and make all methods transactional). How can I control it?
Sorry if some of the questions are confusing because I know only bits and pieces of the Java EE 6 new component model.
#EJB injects EJBs only, but #Inject can be used to inject POJOs rather than EJBs. However, #Inject requires that your archive be a BDA (contain beans.xml for EE 6, or implicitly in EE 7). #Inject also has additional CDI-specific capabilities (scopes, interceptors, etc.), but those capabilities incur extra overhead. Application servers have support for specifying #EJB bindings so that a deployer can choose the target EJB, but #Inject only allows the application developer to choose the target EJB (and it must exist in the application).
If the target is not an EJB, then you must not use #EJB.
It depends whether you're making multiple inter-related queries and then attempting to make business decisions. You need to understand isolation levels and take them into consideration, even for read-only operations.
From Adam Biens Weblog:
You can use both annotations to inject EJBs. Start with #Inject and if you encounter any problems, switch to #EJB.
#Inject does not have any methods / attributes--it is just a plain annotation:
#Target(value = {ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
#Retention(value = RetentionPolicy.RUNTIME)
#Documented
public #interface Inject {
}
On the other hand, the #EJB annotation allows you to pass additional information, which could be useful to reference remote EJBs, or EJBs which cannot be simple injected in the "Convention over Configuration" style:
#Target(value = {ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
#Retention(value = RetentionPolicy.RUNTIME)
public #interface EJB {
public String name() default "";
public String beanName() default "";
public Class beanInterface() default Object.class;
public String mappedName() default "";
}
#Inject is more general than EJB and is part of CDI specification. So if you want to use #Inject, you need an implementation of it in your server.
For POJOs (not EJBs) you have to use #Inject.
Does anyone know how to run unit tests for Liferay portlets? I have found a lot of posts about it (e.g. http://agile-reflections.opnworks.com/2010/06/portlet-unit-testing-with-liferay-6.html) but none works nonetheless.
This may be overkill, but if you're looking for an Enterprise approach with continuous integration testing, this blog gives a very good example: Continuous integration on Liferay: running your Selenium 2 tests on the Tomcat 6 bundle
Unit testing Liferay portlets is quite complicated when ServiceBuilder is utilized.
The reason is that it generates quite heavy services that contain references not only to beans within Portlet, but even to the Portal beans generated by ServiceBuilder.
There are tools like InitUtil.init(); that lets you at least instantiate and use ServiceBuilder entities... not EntityServices though. For that you'd have to use SpringUtil.loadContext(); that requires
System.setProperty("external-properties", "testing.properties");
where testing.properties contains :
spring.configs=META-INF/ext-spring.xml,\
META-INF/base-spring.xml,\
META-INF/dynamic-data-source-spring.xml,\
META-INF/infrastructure-spring.xml,\
META-INF/shard-data-source-spring.xml,\
META-INF/hibernate-spring.xml,\
META-INF/portlet-spring.xml
These are spring definitions to be loaded for testing application context. It all would be OK, but beans from portlet-spring.xml are those heavy services containing references to Portal bean definitions like ResourceService, UserLocalService, CounterLocalService and you would have to load even META-INF/portal-spring.xml and trust me, it's not that easy cause then you'd have to load quite a lot of other stuff.
THE ANSWER:
The truth is, that you most likely won't have to unit test portlet SB services, never. They represent entities with persistence and service layer around. Something that is not to be tested. You just have to mock them and stub their methods, right ?
And the best way for junit and integration testing as to mocking is not using *LocalServiceUtil static classes in your application, because it is almost unmockable.
You just need to create a Spring FactoryBean :
public class PortalFactoryBean implements FactoryBean {
private Class type;
public void setType(final Class type) {
this.type = type;
}
#Override
public Object getObject() throws Exception {
return PortalBeanLocatorUtil.locate(type.getName());
}
#Override
public Class getObjectType() {
return type;
}
}
public class PortletFactoryBean implements FactoryBean {
private Class type;
public void setType(final Class type) {
this.type = type;
}
#Override
public Object getObject() throws Exception {
return PortletBeanLocatorUtil.locate(type.getName());
}
#Override
public Class getObjectType() {
return type;
}
}
<bean id="somePortalBean" class="example.spring.PortalFactoryBean" lazy-init="true">
<property name="type" value="com.liferay.some.util.SomeService"/>
</bean>
<bean id="somePortletBean" class="example.spring.PortletFactoryBean" lazy-init="true">
<property name="type" value="com.example.SomeService"/>
</bean>
#Autowired
private SomeService somePortalBean;
Writing unit/integration tests for this portlet would be quite easy, right ? You just create a spring context for testing and you mock these services :
Using Service Builder is worth it, but you must have some Spring knowledge and play with it for some time. Then it spares a lot of time because it is easy to maintain.
You need to have some third party libraries on classpath.
THe key point is having even portal-impl.jar and other portal dependencies on classpath and having InitUtil.initWithSpring(boolean); load up core spring xml configs that you specify in spring-ext.properties in spring.congigs property, only those services you need. You may need no portal services and only the portlet ones, but this is a problem because your portlet services generated by service builder use the portal services.
Using service builder just needs good knowledge of spring and classloading.
But you need to understand the infrastructure before doing that. There are quite a lot of hacks needed... Like
BeanLocator beanLocator = new BeanLocatorImpl(PortalClassLoaderUtil.getClassLoader(), ac);
PortletBeanLocatorUtil.setBeanLocator("portlet", beanLocator);
I have wsdl and I create classes with wsimport tool. Everything is going ok for SOAP messages but for http:binding GET/POST I get error. Part of the WSDL follows:
<wsdl:binding name="DictServiceHttpPost" type="tns:DictServiceHttpPost">
<http:binding verb="POST" />
...
...
...
<wsdl:port name="DictServiceHttpGet" binding="tns:DictServiceHttpGet">
<http:address location="http://services.aonaware.com/DictService/DictService.asmx" />
</wsdl:port>
<wsdl:port name="DictServiceHttpPost" binding="tns:DictServiceHttpPost">
<http:address location="http://services.aonaware.com/DictService/DictService.asmx" />
</wsdl:port>
wsimport generates classes, for SOAP port its working but for GET/POST but when I use them, I receive error.
Caused by: com.sun.xml.internal.ws.model.RuntimeModelerException: runtime modeler error: SEI invoker.DictServiceHttpPost has method match annotated as BARE but it has more than one parameter bound to body. This is invalid. Please annotate the method with annotation: #SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
at com.sun.xml.internal.ws.model.RuntimeModeler.validateDocBare(RuntimeModeler.java:1247)
at com.sun.xml.internal.ws.model.RuntimeModeler.processDocBareMethod(RuntimeModeler.java:1236)
at com.sun.xml.internal.ws.model.RuntimeModeler.processMethod(RuntimeModeler.java:609)
at com.sun.xml.internal.ws.model.RuntimeModeler.processClass(RuntimeModeler.java:401)
at com.sun.xml.internal.ws.model.RuntimeModeler.buildRuntimeModel(RuntimeModeler.java:240)
at com.sun.xml.internal.ws.client.WSServiceDelegate.createSEIPortInfo(WSServiceDelegate.java:687)
at com.sun.xml.internal.ws.client.WSServiceDelegate.addSEI(WSServiceDelegate.java:675)
at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:330)
at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:313)
at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:295)
at javax.xml.ws.Service.getPort(Service.java:92)
at invoker.DictService.getDictServiceHttpPost(DictService.java:124)
... 29 more
com.sun.xml.internal.ws.model.RuntimeModelerException: runtime modeler error: SEI invoker.DictServiceHttpPost has method match annotated as BARE but it has more than one parameter bound to body. This is invalid. Please annotate the method with annotation: #SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
This happened to me, the problem was that I had a public method in the service implementation, that had more than one parameter but this method was not a service operation. Services marked with: SOAPBinding.ParameterStyle.BARE should only have public methods with only one parameter. My solution was mark this method as private since I was using it from one public method of the service (operation).
Make sure you don't have any public method in your service implementation that has more than one parameter.