I'm trying to reference constant with EL on my JSF page (https://java.net/projects/el-spec/pages/StaticField), but I'm stuck on this exception:
javax.servlet.ServletException: /faces/signup.xhtml #18,85 maxlength="#{signUpBean.USERNAME_MAXLENGTH}": Property 'USERNAME_MAXLENGTH' not found on type com.foo.SignUpBean
I'm using Tomcat 8.0.0-RC1 and here is my backing bean and input declaration:
Bean:
#ManagedBean
#RequestScoped
public class SignUpBean implements Serializable {
public static final int USERNAME_MAXLENGTH = 30;
...
}
Input field on my page:
<input type="text" jsf:id="username" jsf:value="#{signUpBean.username}" maxlength="#{signUpBean.USERNAME_MAXLENGTH}" />
Update:
With maxlength="#{(com.foo.SignUpBean).USERNAME_MAXLENGTH}" I'm getting java.lang.NullPointerException: Argument Error: Parameter value is null
First, off, see BalusC's updated answer for how to properly use constants in EL 3.0 expressions.
Now, with that said, if you just want to get your code working right now with the released version of GlassFish 4.0, you can modify your backing bean in the following way. Your backing bean doesn't have a getter/setter for your field. Backing beans need to have JavaBeans-style properties with getters/setters.
#ManagedBean
#RequestScoped
public class SignUpBean implements Serializable {
private final int USERNAME_MAXLENGTH = 30;
private String username;
...
public int getUSERNAME_MAXLENGTH() {
return USERNAME_MAXLENGTH;
}
public void setUSERNAME_MAXLENGTH(int i) {
// don't set anything, because this is a constant
}
public String getUsername() {
return username;
}
public void setUsername(String u) {
username = u;
}
}
Then your Facelets tag:
<input type="text"
jsf:id="username"
jsf:value="#{signUpBean.username}"
jsf:maxlength="#{signUpBean.USERNAME_MAXLENGTH}" />
That is, don't make the field static. I do recommend switching this over to the correct syntax once JSF is updated in the RI/GlassFish 4.0.
Edit: fixed input tag to use jsf:maxlength.
Related
Rest Controller:
#RequestMapping(value = "/admin/rest/new-subscriptions")
public List<NewSubscriptionDTO> getNewSubscriptions() {
NewSubscriptionDTO dto = new NewSubscriptionDTO();
dto.setId("54");
dto.setName("John Doe");
return Arrays.asList(dto);
}
NewSubscriptionDTO:
package dermatica.web.admin.rx;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.joda.time.DateTime;
import java.io.Serializable;
public class NewSubscriptionDTO implements Serializable {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I get the following exception:
no properties discovered to create BeanSerializer (to avoid exception,
disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
If I annotate the fields with #JsonProperty it work fine.
Is there a way for the serialization to work automatically without needing this annotation?
#JsonProperty auto-generates a getter/setter that Jackson uses to read/write to the fields during serialization/deserialization. Here are some alternative approaches:
Provide your own public getters/setters for all fields
Make the fields public, generally frowned upon, but if you're creating a simple DTO, that may be acceptable.
Setting ObjectMapper Visibility for FIELD to ANY (see here)
Disable the FAIL_ON_EMPTY_BEANS exception (see here)
Given that your DTO class has getters and setters, this should work without #JsonProperty. I wasn't able to reproduce the exact error message you showed, but here are some suggestions that may help:
[Controller] Explicitly specify the method type as GET, either using method = GET or #GetMapping - not necessary, but it's good to be explicit
[Controller] Make sure you annotate the controller class with #RestController, indicating the response is serialized to JSON and wrapped in an HttpResponse object.
[DTO] You don't need to extend Serializable (see here).
The final controller would look like this:
#RestController
public class MyController {
#GetMapping(value = "/admin/rest/new-subscriptions")
public List<MyDTO> getDTO() {
MyDTO dto = new MyDTO();
dto.setId("54");
dto.setName("John Doe");
return Collections.singletonList(dto);
}
}
Response:
[{"id":"54","name":"John Doe"}]
I have wsimport-ed Java classes with standard bean conventions:
public class Request {
protected String vin;
public String getVin() {
return vin;
}
public void setVin(String value) {
this.vin = value;
}
}
I expected to use this class in Kotlin using nice property syntax:
override fun search(request: Request): Response {
log.info("search(vin={})", request.vin);
...
but this code does not compile:
Error:(59, 64) Kotlin: Cannot access 'vin': it is 'protected/*protected and package*/' in 'SmvSearchRequest'
request.getVin() works, of course, but that doesn't look better than Java. Is there some way to treat those classes as property holders?
This was missing pre-M13, it is now fixed in M13, see Youtrack
I have the following interface
#JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "className")
public interface InfoChartInformation {
public String name();
}
And the following implementation (enum):
public class InfoChartSummary {
public static enum Immobilien implements InfoChartInformation {
CITY, CONSTRUCTION_DATE;
}
public static enum Cars implements InfoChartInformation {
POWER, MILEAGE;
}
}
Then I use all of It in the following entity:
#Entity(noClassnameStored = true)
#Converters(InfoChartInformationMorphiaConverter.class)
public class TestEntity{
#Id
public ObjectId id;
#Embedded
public List<InfoChartInformation> order;
}
Jackson, in order to detect the type on the unmarshalling time, will add to every enum on the list the className.
I thought morphia would do the same, but there's no field className in the List of enum and the unmarshalling cannot be done correctly: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassCastException: java.lang.String cannot be cast to com.mongodb
.DBObject
I guess the correct behavior should be to save all the enum route (package+name), not only the enum name. At least in that way the unmarshalling could be performed. There's a way morphia supports that by default or I need to create my own converter (similar to this) ?
I tried creating a Custom Converter:
public class InfoChartInformationMorphiaConverter extends TypeConverter{
public InfoChartInformationMorphiaConverter() {
super(InfoChartInformation.class);
}
#Override
public Object decode(Class targetClass, Object fromDBObject, MappedField optionalExtraInfo) {
if (fromDBObject == null) {
return null;
}
String clazz = fromDBObject.toString().substring(0, fromDBObject.toString().lastIndexOf("."));
String value = fromDBObject.toString().substring(fromDBObject.toString().lastIndexOf(".") + 1);
try {
return Enum.valueOf((Class)Class.forName(clazz), value);
} catch (ClassNotFoundException e) {
return null;
}
}
#Override
public Object encode(final Object value, final MappedField optionalExtraInfo) {
return value.getClass().getName() + "." + ((InfoChartInformation) value).name();
}
}
Then, I added the converter information to morphia morphia.getMapper().getConverters().addConverter(new InfoChartInformationMorphiaConverter());.
However, when serializing (or marshalling) the object to save it into the database, the custom converter is ignored and the Enum is saved using the default Morphia converter (only the enum name).
If I use in the TestEntity class only an attribute InfoChartInformation; instead of the List<>InfoChartInformation>, my customer converter will work. However I need support for List
Use:
public class InfoChartInformationMorphiaConverter extends TypeConverter implements SimpleValueConverter
It is a marker interface required to make your Convertor work.
I got some troubles for attribute binding in JSF 1.2 with EL 1.0
public class Bean {
private String name;
public String getName() {
return name;
}
public Bean setName(String name)
this.name = name;
return this;
}
XHTML that give me "Property 'name' not writable" error on form submit:
..
<h:inputText value="#{bean.name}" />
..
Why? It is a 3rd party lib, there is any workaround to solve that case?
Change signature of setName method like this
public void setName(String name)
this.name = name;
}
If you want second constructor in your Bean class, then it should be designed like this
public Bean (String name)
this.name = name;
}
I found a workaround for that case, but clearly it's not the most elegant way to do:
Create a "pseudo extension" of Bean class:
public class BeanExtension {
private Bean instance = new Bean();
public String getName() {
return instance.getName();
}
public void setName(String name)
instance.setName(name);
}
// omitted instance getter and setter methods
}
Since I wanted to override setName method return to "void", now I must use bean.instance to access it attributes, and bean.name to bind name on JSF with EL.
I am trying to bind a repository to property using Ninject but always get null reference of binding object. I will explain the problem using code below.
public interface IServiceRepository
{
User GetUser(string email);
IQueryable<Statistic> GetStatisticForCurrentMonth(string ip);
void InsertStatistic(ConversionModel conversionModel);
class ServiceRepository : IServiceRepository
{
//Implementation of the Interface
}
I am would like to bind the repository above to class below while the class is created. Unfortunately Repository object is always null. Maybe I have misunderstood how Ninject is working? How to solve the problem?
public class Converter
{
[Inject]
public static IServiceRepository Repository { get; set; }
private static Converter _converter;
public static Converter Instance
{
get { return _Converter ?? (_Converter = new Converter ());
}
}
Ninject activator code
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IServiceRepository>().ToMethod(context => Converter.Repository);
}
Update
I have tried to rewrite code like this
public class Converter
{
private readonly IServiceRepository _repository;
public Converter(IServiceRepository repository)
{
_repository = repository;
}
//skip code
}
The test...
[TestMethod]
public void ConverterInstanceCreated()
{
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<IServiceRepository>().To<ServiceRepository>();
Assert.IsNotNull(kernel.Get<Converter>());
}
}
gives exception
Test method PC.Tests.NinjectTest.ConverterInstanceCreated threw exception:
Ninject.ActivationException: Error activating IServiceRepository
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IServiceRepository into parameter repository of constructor of type Converter
1) Request for Converter
I just lost, I am trying to understand how Ninject is working for about week without any success. In my case why this exception is thrown?
Also please someone post working example with one repository injection to singleton class.
Ninject does not inject statics. Change the coynverter to a non-static class and configure it as Singleton in ninject. Also use constructor injection and make the repo a private field.
Now you can inject the converter to the constructors where you need it.
Even though you are using Property injection and not Constructor injection I think it would still be
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IServiceRepository>().To<ServiceRepository>();
}
As ninject still just needs to know what concrete type to map to the Interface
I haven't tested this so apologies if it's wrong.