Java-config counterpart of wss:binding? - java

Ok, so here's something I've been googling for for hours with no success... Finally i can only hope some Spring-magician reads and answers this question. :)
I'm upgrading an old web application (Spring 2.x-based) to Spring 4.2.x and while adding new features I've decided to completely move away from XML-based config. (Again: i don't want to have any Spring XML files in the project!)
I've converted pretty much everything, but the last thing i can't resolve is finding the correct Java-config counterpart of:
<ws:service id="MySoapService" bean="#ServiceImpl" />
<wss:binding service="#MySoapService" url="/1.0/soap" />
ws/wss namespaces come from:
xmlns:ws="http://jax-ws.dev.java.net/spring/core"
xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
So what i'm trying to do is exporting #WebService annotated classes, but with Java-config instead of XML.
Additional infos:
I've tried using SimpleJaxWsServiceExporter, but that one leaves me with a "java.net.BindException: Address already in use: bind", regardless of what port i'm using...
The application has two servlets: one is a normal Spring MVC Dispatcher for the new REST API and another com.sun.xml.ws.transport.http.servlet.WSSpringServlet which should make the above mentioned JAX-WS service available.
I'm trying to resolve things with pure JAX-WS RI, no CXF or any other library. The application is huge enough already... :(

You can achieve this by injecting your endpoint and the following helper method (note that my approach uses a base class BaseEndpoint for each endpoint):
#Configuration
public WebserviceConfiguration {
#Inject
private FooEndpoint fooEndpoint;
#Bean
public SpringBinding fooEndpoint() throws Exception {
return bind(fooEndpoint, "ws/bar");
}
private SpringBinding bind(BaseEndpoint endpoint, String url) throws Exception {
SpringService springService = new SpringService();
springService.setBean(endpoint);
SpringBinding binding = new SpringBinding();
binding.setService(springService.getObject());
binding.setUrl(url);
return binding;
}
}

Apparently there's no solution (yet?) - after quite a few more hours of googling around, i've found only this ticket:
https://java.net/jira/browse/JAX_WS_COMMONS-134
Looking at its date and status (and by noting the fact that devs didn't even respond to it, even a year has passed), i assume it's safe to state that JAX-WS Commons spring integration will not support Java config in the foreseeable future.

Related

How to dynamically lookup an EJB at runtime

I have this scenario where i have my EJB3 beans in a jar file, deployed successfully to Jboss EAP-6.4.
Then I have another web project that looks up these EJB's inside a REST POJO class. I can currently access the EJB's from inside the web project using #Inject and #EJB, but my use case is one that i don't know which beans i need to load until runtime and the list is not static, so i might need to lookup 10 EJB's or none for a particular request etc.
I know I can possibly use
InitialContext.lookup('ejb:/.....')
to retrieve my EJB beans from inside the web project, but is there a way that i can retrieve them without that round trip(i believe), or maybe what am just looking for is a more elegant way to do EJB look-up at runtime just like the statically typed #EJB and #Inject versions.
Any suggestions are greatly appreciated.
EDIT
In my REST POJO classes i don't want to hard code any #Inject or #EJB annotations, rather i want that when a request comes in i look-up(for lack of better word) the EJB's that will handle the request, so all the decision is made at runtime really, as shown below
#Path("/path")
public class TestService {
#GET("/{id}")
public String loadGetPath(#Param id int id){
//at this point i want to dynamically resolve the EJB based on
//the value of id
}
}
Whoopdicity blog: Developing a dynamic JEE service client with CDI seems to have what you are looking for. At the end it claims you can do:
public class MyServiceConsumer {
#Inject #ServiceClient
private MyBusinessService service;
...
}
Instead of
public class MyServiceConsumer {
#EJB(lookup="...")
private MyBusinessService service;
...
}

Building custom java config annotations - similar to custom XML namespaces

We're building a framework on top of Spring & Spring MVC. Our framework is quite mature at this point - about 2 years old and is used widely within our organization. Our framework is very modular (much like spring itself is). There are various modules that can be used independently or together. When used together they provide many benefits to the end user. We have built a handful custom spring XML namespaces (NamespaceHandlers, BeanDefinitionParsers, etc). Each module provides their own which brings in its own set of XML configuration elements. This is all working great for us and has been a really big win for us.
What we'd like to do now is move away from XML-based configuration and into java config. My idea/thought is for each module to introduce a set of java config annotations that can be used (something similar to the #EnableCaching, #EnableMBeanExport annotations). My question is this - even if I create my annotations - how do I "wire" them in so that if they are present I can do "stuff"? This would be similar conceptually to the NamespaceHandlers & BeanDefinitionParsers. I can't find any documentation anywhere as to how to get started.
I've thought about creating some custom abstract base classes which do what I need them to do - but the problem is when it comes to the end user's application - they can only extend a single class. I need a flexible way for each module in my framework to expose its own custom configuration that end user applications can use, just like they use our XML namespace elements.
Here's a glimpse as to what we do in XML (not full application context file - just a blurb from it pertaining to our custom XML namespaces):
<atom-web:web/>
<atom-web:logging/>
<atom-web:security entitlementsProvider="XML" xmlRefreshInterval="${cache.refresh.interval.ms}"/>
<atom-profile:profile caching="IN_MEMORY" entryExpiryDelay="${cache.refresh.interval.ms}"/>
<atom-prefs:preferences backingStoreUrl="${pref.backingStore.url}"/>
<atom-content:content contentServerBaseUrl="${content.server.url}" contentServerFileUrl="${content.server.file.url}" site="${site.name}" contentTaskExecutor="contentTaskExecutor" snippetCaching="IN_MEMORY" cacheRefreshInterval="${cache.refresh.interval.ms}"/>
<bean id="contentTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" p:corePoolSize="3" p:maxPoolSize="20"/>
What I'm envisioning is some kind of set of annotations - something like this:
#EnableAtomWebApplication
#EnableAtomWebLogging
#EnableAtomWebSecurity(entitlementsProvider=EntitlementsProvider.XML, xmlRefreshDelay=120000)
#EnableAtomProfile(caching=CachingType.IN_MEMORY, expiryDelay=120000)
// Other annotations for rest of modules
#Configuration
public class ConfigurationClass {
// Rest of configuration in here
}
Any help here would be greatly appreciated. I'm not quite sure where to start and can't really find any documentation anywhere to help me get started.
So after thinking about this a bit I think I've found the correct starting point. I wanted to throw this out there for anyone who might be able to say "yeah thats the right place" or "no you aren't looking in the correct place".
Using my example above
#EnableAtomProfile(caching=CachingType.IN_MEMORY, expiryDelay=120000)
I would create an annotation for the #EnableAtomProfile annotation like this:
#Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
#Target(value={java.lang.annotation.ElementType.TYPE})
#Documented
#Import({AtomProfileBeanDefinitionRegistrar.class})
public #interface EnableAtomProfile {
CachingType caching() default CachingType.NONE;
long expiryDelay default 0;
}
The AtomProfileBeanDefinitionRegistrar class would implement org.springframework.context.annotation.ImportBeanDefinitionRegistrar and do any of the necessary stuff that I'm currently doing in my BeanDefinitionParser
You can have a BeanPostProcessor defined, which would basically:
inspect every single bean created
with reflection check if the object's class is annotated with #YourAnnotation
and if it is, then apply some custom logic - e.g. package the object into some other class or something
Reference:
Spring docs on BeanPostProcessors
source code for RequiredAnnotationBeanPostProcessor, which is a BeanPostProcessor which analyzes annotations

How to register spring bean in grails that needs a reference to a filter bean

I am trying to use spring security oauth (library not grails plugin, there is only an extremely outdated grails plugin).
I want my app to be an OAuth 1.0a provider (not OAuth 2). The OAuth2 part of spring-security-oauth does not seem to have this problem, because it does not require a reference to the filterchain in the provider config.
What i want is to configure it as shown here: https://github.com/spring-projects/spring-security-oauth/blob/master/samples/oauth/sparklr/src/main/webapp/WEB-INF/applicationContext.xml
I translated this to the groovy syntax of grails:
consumerDetails(InMemoryConsumerDetailsService)
tokenServices(InMemoryProviderTokenServices)
xmlns oauth: "http://www.springframework.org/schema/security/oauth"
oauth.'consumer-details-service'(id:'consumerDetails') {
oauth.consumer(name: 'AndroidRegisterApp', key:'testkey', secret:"testkey123", resourceName:'mobileApi', resourceDescription:'Register devices via mobile app')
}
oauth.provider(
'consumer-details-service-ref': "consumerDetails",
'token-services-ref':'tokenServices',
'request-token-url':'/oauth/request_token',
'authenticate-token-url':'/oauth/authorize',
'access-granted-url':'/requestTokenAuthorized',
'access-token-url':'/oauth/access_token',
'filter-chain-ref':'springSecurityFilterChainProxy',
'require10a':'true'
)
The problem is that when OAuthProviderBeanDefinitionParser parses this config during grails app start, the springSecurityFilterChainProxy does not yet exist so it fails here:
https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/OAuthProviderBeanDefinitionParser.java#L179 while calling ConfigUtils.findFilterChain the important line in there is:
parserContext.getRegistry().getBeanDefinition(filterChainRef)
which fails because "springSecurityFilterChainProxy" just doesn't exist in the parserContext (I guess because it only gets created later on). I also tried to postpone this initialization, by putting it in the bootstrap code like this:
def initOauthProvider() {
def bb = new BeanBuilder(grailsApplication.getMainContext())
bb.beans {
// same bean initialization code as above
}
}
this also fails because here i only have the beans in the parserContext that are part of my definition (it doesn't see any other grails beans)
is there any way i can fix this? I've seen that the BeanBuilder can also be initialized with a RuntimeSpringConfiguration object but i haven't found any way how to get this from my grails app.
I am using:
Grails 2.2.4
spring-security-oauth:1.0.5 with these excludes: 'spring-security-web', 'spring-security-core', 'spring-asm'
spring-security-core:2.0-RC2 grails plugin
You may try to explicitly define all the spring bean dependencies (references) in grails-app/conf/spring/resources.groovy file.
Here is a sample syntax:
// resources.groovy
beans = {
yourBean(com.company.YourBean) {
springSecurityService = ref('springSecurityService')
otherService = ref('otherService')
anotherService = ref('anotherService')
}
}
So, in this case, you should get all three springSecurityService, otherService and anotherService initialized and accessible from within the yourBean bean.
add your existing xml file in resource folder and use the below
beans = {
importBeans('classpath:/applicationContext-services.xml')
}

Conditionally creating beans in spring

Right now I'm exposing the service layer of my application using spring remoting's RMI/SOAP/JMS/Hessian/Burlap/HttpInvoker exporters. What I'd like is to allow the user to somehow define which of these remoting mechanisms they'd like enabled (rather than enabling all of them), then only create those exporter beans.
I was hoping that spring's application context xml's had support for putting in conditional blocks around portions of the xml. However, from what I've seen so far there's nothing in the standard spring distribution that allows you to do something like this.
Are there any other ways to achieve what I'm trying to do?
I am going to assume that you are looking to configure your application based on your environment, as in... for production I want to use this beans, in dev these other ...
As Ralph is saying, since Spring 3.1 you have profiles... But the key, is that you understand that you should put your environment based beans in different configuration files... so you could have something like dev-beans.xml, prod-beans.xml... Then in your main spring file, then you just invoke the appropriate one based on the environment that you are using... So profiles are only technique to do so... But you can also use other techniques, like have a system environmental variable, or pass a parameter in your build to decide which beans you want to use
You could realize this by using a Spring #Configuration bean, so you can construct your beans in java code. (see http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-java)
#Configuration
public class AppConfig {
#Bean
public MyService myService() {
if ( userSettingIshessian ) {
return new HessianExporter();
}else {
return new BurlapExporter();
}
}
}
Of course you need to get the user setting from somewhere, a system parameter would be easy, or config file, or something else.
Spring 3.1 has the concept of Profiles. My you can use them.

spring faces without spring flow

I'm starting a new JSF (2) project. I realize that pure JSF has some limitation and I'm planning to drop in spring. JSF is a relatively new approach in spring (there is not even a tag spring-faces in stackoverflow :-) ), jsp being the classic way. I need the best available adjustment of the technology stack.
1) do i need to use spring web flow too?
2) is it viable to use just spring faces (that seems to come as a part of web flow) + spring mvc+ JPA?
3) is there any good example of such a configuration?
I'm using JSF 2 together with Spring 3 for Dependency Injection etc.
I'm not familiar with Web Flow and I don't use it.
In your faces-config.xml you can register the Spring SpringBeanFacesELResolver.
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
Then you can access Spring managed beans in your JSF code!
Have a look at the Spring documentation and the API docs.
If you do not have heavy wizard-specific views in your application, I doubt you'll actually need to use SWF.
The easiest solution is actually the one Sebi told you - register the Spring EL Resolver and mark your controller classes with appropriate stereotype (most usually, #Controller) and desired scope. From there on you should be able to get references to Spring-managed beans via manual- or autowiring. And that's all there is to it - no faces-config.xml bean managment and no "double IoC" overhead. Once it's in Spring context, the managed controller is dereferenced easily from facelet via #{} EL-notation.
For example:
TestController.java:
#Controller("myController")
#Scope("request")
public class TestController {
#Autowired
private SomeSpringManagedBean someBean;
private String someViewProperty;
public String getSomeViewProperty() {
return someViewProperty;
}
public void setSomeViewProperty(String arg) {
this.someViewProperty = arg;
}
......
}
TestView.jspx:
<p:inputText value="#{myController.someViewProperty}" />
We've lost about 2 weeks trying to tie in SWF together with JSF 1.2 - only to discover that once we actually got it working with the latest version of the IceFaces that support JSF 1.2, the IceFaces had a feature/bug so nasty that it simply wouldn't render the view and had gotten stuck in Phase 5 without throwing any exception or reporting anything useful (the issue became fixed in a 1.8.2-GA version of IceFaces that isn't obtainable without purchasing the license).
EDIT: I noticed basically a similar SO-thread here.

Categories