I am a newbie for struts. I have a requirement to Migrate from struts1 to struts2 application. I have to pass HttpServlet to one service which was already written in struts1 application. My controller has:
class myController{
HttpServletRequest request;
HttpServlet servlet;
}
where
HttpServletRequest request= org.apache.struts2.dispatcher.StrutsRequestWrapper but HttpServlet servlet = null
Since my service takes servlet as input parameter I am not able to get the output value as servlet is null.
Is there any way in Struts2 to set HttpServlet value? Please suggest.
Related
Using DropWizard(Jersey Server), Is it possible to access HttpServletRequest from an Authenticator?
I would give it an attribute.
I tried with:
#Context
private HttpServletRequest servletRequest;
But it's not injected.
I registered my Authenticator using:
env.jersey().register(
new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<User>().setAuthenticator(new FooAuthentificator())
.setRealm("Realm").buildAuthFilter()));
It's possible, but the problem is, the Authenticator never goes through the DI lifecycle, so it never gets a chance to get injected. What we can do though is explicitly inject it ourselves. To do that, we need to get a hold of the ServiceLocator (which is the main IoC container, kind of like ApplicationContext with Spring). Once we have the ServiceLocator, we can call locator.inject(anyObject) to explicitly resolve any injection dependencies.
The easiest place to get the ServiceLocator, when configuring the app, is in a Feature. Here we can also register Jersey components. Calling register on the FeatureContext (seen below) is just like calling env.jersey().register(...) with Dropwizard, it has the same effect. So we can do
public class AuthenticatorFeature implements Feature {
#Override
public boolean configure(FeatureContext ctx) {
ServiceLocator locator = ServiceLocatorProvider.getServiceLocator(ctx);
TestAuthenticator authenticator = new TestAuthenticator();
locator.inject(authenticator);
ctx.register(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<User>()
.setAuthenticator(authenticator)
.setRealm("SEC REALM")
.buildAuthFilter()));
ctx.register(new AuthValueFactoryProvider.Binder<>(User.class));
return true;
}
}
You can see that explicitly inject the authenticator, with the call to locator.inject(authenticator). Then we register this feature through Dropwizard
env.jersey().register(new AuthenticatorFeature());
Tested, and works fine.
Note, if you are wondering how it's possible to inject the HttpServletRequest, when there is no current request, it's because a proxy is injected. Same thing as if you were to inject the request into a Jersey filter, the same thing happens; a proxy is injected, as there is only a singleton filter, but the request changes from request to request, so a proxy needs to be injected.
See Also:
Injecting Request Scoped Objects into Singleton Scoped Object with HK2 and Jersey
What should work properly if I do not specify the converter-id and(or) forClass in determining the #FacesConverter annotation?
For example:
#FacesConverter
public class SplitConverter implements Converter{
#Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
//...
}
#Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
//...
}
After registred in faces-config.xml and use that on .xhtml page:
<h:inputText id="badges" value="#{article.badges}"
required="true">
<f:converter converterId="com.katcgr.SplitConverter" />
</h:inputText>
And all is work. The documentation say that
if converter-id is the empty string, Application.addConverter(java.lang.Class,java.lang.String) is called, passing the converter-for-class as the first argument and the derived converter-class as the second argument.
But why everything works fine even if I not specified the forClass ?
After registred in faces-config.xml
Registration via #FacesConverter and <converter> in faces-config.xml are mutually exclusive whereby the XML registration overrides any annotation registration. So, when your converter is referenced via the converter ID as registered in XML, then the converter instance behaves basically exactly as if it had no annotations. If you remove the XML registration, then you should have retrieved the below exception on specified converterId:
javax.faces.FacesException: Expression Error: Named Object: com.katcgr.SplitConverter not found.
at com.sun.faces.application.ApplicationImpl.createConverter(ApplicationImpl.java:1339)
at javax.faces.application.ApplicationWrapper.createConverter(ApplicationWrapper.java:393)
at com.sun.faces.facelets.tag.jsf.ConverterTagHandlerDelegateImpl.createConverter(ConverterTagHandlerDelegateImpl.java:158)
...
This would basically only work if you had a
#FacesConverter("com.katcgr.SplitConverter")
If you however remove both the XML configuration and the <f:converter>, then it will "work" because the #FacesConverter without an explicit forClass will be automatically invoked for every bean property which is an instance of java.lang.Object (basically, everything), which does not have a more specific converter already registered. In other words, your converter will behave like:
#FacesConverter(forClass=Object.class)
It hopefully doesn't need an elaborate explanation that this is a terribly bad idea. It will also confuse PrimeFaces, because it will then internally initialize and use it as default converter for String class.
I need to set a ServletRequest attribute within a Struts2 interceptor (not action class).
Does the ActionContext expose a Map<String, Object> to control request attributes, like it does for session attributes?
I see ActionContext implements a map. Is the ActionContext itself a wrapper for the request attributes?
The ActionContext contains a request key that holds the request object. To answer you question: no the ActionContext is not a wrapper for request, however the request in Struts2 is a wrapper for the servlet request.
You can get the request from the action context like
HttpServletRequest request = ServletActionContext.getRequest();
That way is useful in interceptors, but in action better to implement ServletRequestAware
protected HttpServletRequest request;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
For code that is not inside an action class (RequestAware should be used for action classes), Struts2 can expose the servlet request attributes as a Map. They are accessible with:
Map request = (Map) ActionContext.getContext().get("request");
See Strus2 documentation for more details.
I want to use ManagedBean in my Converter. The ManagedBean is responsible for getting data from database. In Converter I want to convert string into object which must be get from database.
This is my Converter
#FacesConverter(forClass=Gallery.class, value="galleryConverter")
public class GalleryConverter implements Converter {
// of course this one is null
#ManagedProperty(value="#{galleryContainer}")
private GalleryContainer galleryContainer;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String galleryId) {
return galleryContainer.findGallery(galleryId);
...
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object gallery) {
...
}
}
I know that galleryContainer will be null and if I want to inject ManagedBean into Converter I can mark it as ManagedBean too. The problem is that I want to do it in beautiful way, I don't want to look for some 'strange solution'. Maybe the problem is in my application? Maybe there is some other good solution to create object which must get data from database and used in converter? I want also to mention that I will prefer to use DependencyInjection instead of creating new object using new statement (it is easier to test and maintain). Any suggestions?
Instead of using #FacesConverter you should use #ManagedBean, because currently faces converter isn't a valid injection target. Nonetheless, you can choose your converter to be a managed bean, thus refer to it in your view as converter="#{yourConverter}" (by managed bean name) instead of converter="yourConverter" (by converter id).
Basic usage example:
#ManagedBean
#RequestScoped
public class YourConverter implements Converter {
#ManagedProperty...
...
//implementation of converter methods
}
Of course, reading BalusC's invaluable Communication in JSF 2.0 will shed some light on this question as well.
It is also worth mentioning that the scope of your converter bean may be changed to, for example, application or session, if it is not supposed to hold any state.
public class Servlet2Stateless extends HttpServlet {
#EJB private HelloUserLocal helloUser;
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
out.println(newSess.getName());
}
will above line of code work when I have EJB and Servlet deployed on different servers? or I need to call it through traditional way????
If the EJB resides on the different server than your client (Servlet) than you cannot use the dependency injection with #EJB annotation.
I guess that you'll need to go with the old JNDI way.
According to EJB 3.1 spec, you can use #EJB annotation in a variety of clients, including servlets which is your case.
The problem is that you are running client and server in different hosts. Depending on the server you are using, you might be able to use the EJB annotation. This post explains how to do it in Weblogic.
Needless to say you have to define the server EJB as #Remote in either case.
If your container also supports CDI, you could write a CDI producer method for the bean whcih does the JNDI lookup. Then you can at least separate the lookup from the injection site.
What about using dependency injection in a standalone client ?