Is there a way to get the #WebServlet name of a Servlet by using the class name?
I have access to the ServletContext if that helps.
The class name is safer to use because it gets refactored if I change it.
I'm trying to get a Servlet's mappings as follows
String servletName = "someServlet"
Collection<String> mappings = servletContext.getServletRegistration(servletName).getMappings();
But rather than simply hard coding a value for the servletName I would prefer to retrieve it safely from the HttpServlet class.
The ServletContext has another method which returns all servlet registrations: getServletRegistrations(). The ServletRegistration interface has in turn a getClassName() method which is of your interest:
String getClassName()
Gets the fully qualified class name of the Servlet or Filter that is represented by this Registration.
So, this should do:
Class<? extends HttpServlet> servletClass = YourServlet.class;
Optional<? extends ServletRegistration> optionalRegistration = servletContext
.getServletRegistrations().values().stream()
.filter(registration -> registration.getClassName().equals(servletClass.getName()))
.findFirst();
if (optionalRegistration.isPresent()) {
ServletRegistration registration = optionalRegistration.get();
String servletName = registration.getName();
Collection<String> servletMappings = registration.getMappings();
// ...
}
The servletName is your answer. But as you can see, the mappings are readily available without the need for yet another ServletContext#getServletRegistration() call with the servletName.
Related
Do I ever have to specify class name for #WebListener annotation like I have to do for #WebServlet("/MyClassname") ?
In my application just #WebListener works fine, but I have only single ServletContextListener - maybe if I had a few it would have been different?
#WebServlet("/MyServlet")
public class MyServlet extends HttpServlet {
...
}
#WebListener
public class InitWebAppServlet implements ServletContextListener {
...
}
The value in #WebServlet is not a class name. It is a URL path. When using only a single parameter like you show it is the equivalent of:
#WebServlet(urlPatterns = {"/MyServlet"})
Your code could just as easily have been:
#WebServlet("/bobsyouruncle")
public class MyServlet extends HttpServlet {
...
}
That means that you'd access your servlet with the url /bobsyouruncle instead of /MyServlet. See the WebServlet javadocs for more details. Note that for annotations if you have only a single parameter it sets the element value.
The optional value of the #WebListener parameter is for a description of the listener (see the WebListener javadocs). It is, again, not a class name. You can have as many #WebListener classes as you'd like though by using the annotation method instead of the web.xml method you cannot guarantee the order in which the servlet container runs them.
I'm trying to follow a tutorial on using the unit of work and repository pattern on MSDN but I've stumbled at the below:
private UnitOfWork unitOfWork = new UnitOfWork();
"This code adds a class variable for the UnitOfWork class. (If you were using interfaces here, you wouldn't initialize the variable here; instead, you'd implement a pattern of two constructors"
Basically, I need to call my UnitOfWork class in my LogController without actually using the above code as I'm using an interface? How is this possible? I'm not sure what it means by 'two constructors'.
Any advice would be appreiciated
In your class you define
Private IUnitOfWork _unitOfWork = null;
And you have one constructor which accepts an IUnitOfWork so the caller can pass in an implementation:
Public MyClass (IUnitOfWork unitOfWork) {
_unitOfWork = unitOfWork;
}
And you have another which does not, but knows how to go and find which implementation to create. Either it can use a default implementation, or it can go to some config file you've written to define which type to use, etc.
Within the MyClass you still call _unitOfWork.whateverMethod()
In my unit tests I usually use reflection to manually inject a mock to the tested class' private field:
static void setFieldValue(Object instance, String fieldName, Object fieldValue, Class instanceClass) {
def field = instanceClass.getDeclaredField(fieldName)
field.accessible = true
field.set(instance, fieldValue)
}
Where instanceClass is the class/superclass, where the class is actually declared. How can I make it work or achieve same result for a private field being declared on a groovy trait?
My IDE helped me - just use the # attribute access notation, where the fieldname is package_dots_replaced_with_underscore_TraitName__fieldName, e.g.
testee.#pl_kamilroman_DeleteEntityBean__messages
I have a big set of classes (like more that 100) and they are all extend from some abstract class, let's call it ParentClass. Let's call child classes ChildA,ChildB, etc. How can I register custom deserializer for all children and get class type inside my Deserializer?
I tried:
module.addDeserializer(ParentClass.class, new MyObjectDeserializer());
but it does not work.
I want to skip doing (what is working):
module.addDeserializer(ChildA.class, new MyObjectDeserializer(ChildA.class));
module.addDeserializer(ChildB.class, new MyObjectDeserializer(ChildB.class));
module.addDeserializer(ChildC.class, new MyObjectDeserializer(ChildC.class));
//etc......
Class type should be known, as I am use Jackson for spring #RequestBody method, what have defined class name there.
Any ideas how this can be done?
As far as I know, I don't think there is a mechanism in jackson that will address your exact needs.
However, there are a couple alternatives you can try.
Deserializing polymorphic types with Jackson describes one such alternative, however, you would still need to explicitly define all of the supported subtypes.
Another alternative that would not require you to explicitly define deserialization relationships would be to change your class hierarchy from one of inheritance to that of a container.
For example, converting your abstract parent class to a container like so:
public class DataContainer<T> {
String commonString;
Integer commonInteger;
T subData;
}
Would allow you to simply define in your controller input function as
public String controllerFunction(DataContainer<ClassA> classA);
without a need to define all these subclass deserializations.
Late to the party but I had a similar problem which I solved by registering a custom Deserializers to my SimpleModule. The code is in Kotlin but it should be easy to port it to Java.
The class itself:
class UseBaseClassSimpleDeserializers(
private val baseClass: Class<*>,
private val baseClassDeserializer: JsonDeserializer<*>
) : SimpleDeserializers() {
#Throws(JsonMappingException::class)
override fun findBeanDeserializer(
type: JavaType?,
config: DeserializationConfig?,
beanDesc: BeanDescription?
): JsonDeserializer<*>? {
val beanDeserializer = super.findBeanDeserializer(type, config, beanDesc)
return if (beanDeserializer == null && baseClass.isAssignableFrom(type!!.rawClass)) {
baseClassDeserializer
} else {
beanDeserializer
}
}
}
How to register the custom Deserializers class to a SimpleModule:
val simpleModule = SimpleModule()
simpleModule.setDeserializers(UseBaseClassSimpleDeserializers(ParentClass::class.java, ParentClassDeserializer()))
Below is my controller. My program generates an output, based on a form input. Across the project, there are multiple input forms, that generate the output object. So, the essential flow is the same. So I want a single multi-action controller that does all of that.
Challenges:
1. The service classes change. Although all services implement the same interface, and controller calls the same interface method.
2. The input objects change. Although the input objects do not have any methods other than setters, and getters. So I let them all implement an empty interface.
Questions:
How do I change the qualifier, based on the path. Can I use path variables?
Suppose the path has this value -> singleton. Then my corresponding bean names would be singletonService and singletonInput. I want to make a constant class that has stores this mapping information. So, can I call that from inside the qualifier, using some Spring Expression Language? Example, instead of Qualifier(variablePathName) -> Qualifier(getQualifierName['variablePathName']) Something like that?
Please also clarify the theory behind this. From what I understand, beans are created, autowired before the Request are mapped... Does this mean that what I'm trying to achieve here is simply not possible. In that case, would you suggest making Controller-service pairs for handling each request, with basically the same code? But I feel there must be some way to achieve what I'm trying...
Code:
#Cotroller
#RequestMapping(value="/generate/{path}")
public class TestController {
#Autowired
#Qualifier(......)
private IService service;
#Autowired
#Qualifier(......)
IUserInput userInput;
#RequestMapping(method = RequestMethod.POST)
//Some handler method
}
You're right in that the autowiring is all done once up front (point 3). You wouldn't be able to achieve what you want using fields annotated #Autowired and #Qualifier - as these fields would always reference the same bean instance.
You may be better to ask Spring for the particular service bean by name - based on the path variable. You could do it within a single controller instance. For example:
#Cotroller
#RequestMapping(value="/generate/{path}")
public class TestController {
#Autowired
private ApplicationContext applicationContext;
#RequestMapping(method = RequestMethod.POST)
public String someHandlerMethod(#PathVariable String path) {
IService service = (IService) applicationContext.getBean(path + "Service");
IUserInput userInput = (IUserInput) applicationContext.getBean(path + "UserInput");
// Logic using path specific IService and IUserInput
}
}