I understand the responsibility chain pattern. And I have such a question. As can be seen from my chain of responsibility, if the method does not return the locale to me, then it returns null. How can I go to the next item in the chain if it returns null?
public abstract class StandardLocaleHandler {
protected StandardLocaleHandler localeHandler;
public StandardLocaleHandler() {
this.localeHandler = null;
}
protected abstract Locale getTrueLocale(HttpServletRequest req, HttpServletResponse resp, List<String> localeList, String defaultLocale, Integer cookieAge);
public void setNext(StandardLocaleHandler localeHandler) {
this.localeHandler = localeHandler;
}
public StandardLocaleHandler getNext() {
return localeHandler;
}
}
public class GetLocaleByAvailable extends StandardLocaleHandler {
#Override
protected Locale getTrueLocale(HttpServletRequest req, HttpServletResponse resp, List<String> localeList, String defaultLocale, Integer cookieAge) {
if (isNull(req.getSession().getAttribute(LANG_ATTRIBUTE)) && isNull(req.getCookies())) {
return setAvailable(req, resp, localeList, defaultLocale, cookieAge);
}
return null;
}
}
public class GetLocaleBySession extends StandardLocaleHandler {
#Override
protected Locale getTrueLocale(HttpServletRequest req, HttpServletResponse resp, List<String> localeList, String defaultLocale, Integer cookieAge) {
if (nonNull(req.getSession().getAttribute(LANG_ATTRIBUTE))) {
LOG.debug(req.getParameter(LANG_ATTRIBUTE));
return new Locale((String) req.getSession().getAttribute(LANG_ATTRIBUTE));
}
return null;
}
}
I formed my chain of repsonsibility on this way:
public class ChainBuilder {
private List<StandardLocaleHandler> localeHandlers = new ArrayList<>();
public void addToFilterList(StandardLocaleHandler filter) {
if (!localeHandlers.contains(filter)) {
localeHandlers.add(filter);
} else {
throw new IllegalArgumentException("Already in the list");
}
}
public StandardLocaleHandler createChainOfResponsibility() {
for (int i = 0; i < localeHandlers.size() - 1; i++) {
localeHandlers.get(i).setNext(localeHandlers.get(i + 1));
}
return localeHandlers.get(0);
}
}
ChainBuilder builder = new ChainBuilder();
builder.addToFilterList(new GetLocaleByAvailable());
builder.addToFilterList(new GetLocaleByParam());
builder.addToFilterList(new GetLocaleBySession());
builder.addToFilterList(new GetLocaleByCookie());
StandardLocaleHandler handler = builder.createChainOfResponsibility();
return handler.getTrueLocale(req, resp, localeList, defaultLocale, cookieAge);
How can I go to the next item in the chain if it returns null?
public abstract class StandardLocaleHandler {
public final Locale getTrueLocale() {
Locale local = getTrueLocaleInternal();
return local == null && localeHandler != null ? localeHandler.getTrueLocale() : local;
}
protected abstract Locale getTrueLocaleInternal();
}
public class GetLocaleByAvailable extends StandardLocaleHandler {
#Override
protected Locale getTrueLocaleInternal() {
// TODO logic
return null;
}
}
You need to change code to something like this
public class GetLocaleByAvailable extends StandardLocaleHandler {
#Override
protected Locale getTrueLocale(HttpServletRequest req, HttpServletResponse resp, List<String> localeList, String defaultLocale, Integer cookieAge) {
Locale result = null;
if (isNull(req.getSession().getAttribute(LANG_ATTRIBUTE)) && isNull(req.getCookies())) {
result = setAvailable(req, resp, localeList, defaultLocale, cookieAge);
}
if (result == null) {
StandardLocaleHandler nextHandler = getNext();
if (nextHandler == null) {
return nextHandler.getTrueLocale(....);
}
}
return result;
}
}
And the same for another Handler class.
Related
I have below Java code to prevent X-FRAME-OPTIONS header being set for specific product responses
public class ResponseHeaderValve extends ValveBase {
private static final Logger LOGGER = Logger.getLogger(ResponseHeaderValve.class.getName());
private static final String PRODUCT_NAME = "PRODUCT_NAME";
#Override
public void invoke(Request request, Response response) throws ServletException, IOException {
try {
HttpSession session = request.getSession();
String productName = (String) session.getAttribute(PRODUCT_NAME);
if (productName == null && request.getParameterMap().containsKey(PRODUCT_NAME)) {
productName = request.getParameter(PRODUCT_NAME);
}
if (productName != null && productName.equalsIgnoreCase("product1")) {
HttpServletResponse httpServletResponse = new HttpServletResponseWrapper(response.getResponse()) {
public void addHeader(String name, String value) {
if (!name.equalsIgnoreCase("X-FRAME-OPTIONS")) {
super.setHeader(name, value);
}
}
public void setHeader(String name, String value) {
if (!name.equalsIgnoreCase("X-FRAME-OPTIONS")) {
super.setHeader(name, value);
}
}
};
this.getNext().invoke(request,httpServletResponse);
} else {
this.getNext().invoke(request, response);
}
}
catch(Exception e){
LOGGER.log(Level.INFO, "Exception in ResponseHeaderValve: invoke():", e);
}
}
}
For cases productName equals "product1" using HttpServletResponseWrapper I tried to prevent header being set.
I have to pass request, httpServletResponse to the next valve using invoke method, but org.apache.catalina.valve invoke(Request,Response) method does not allow passing httpServletResponse. I have tried casting (Response)httpServletResponse, it did not work throws ClassCastException. How can I proceed?
I am trying to send POST Request from Android to Spring via Retrofit from past 2 days. I have tried plenty of solutions regarding this, but nothing seems to be working. So, asking here finally to be able to get some help.
So, i am trying to send a simple Object from Android to Spring via retrofit. From android side i have verified the values sent by me and it gives me correct value.(I have debugged it via Android's debugging mode). But on spring side i got null values.
This is my code ->
function foo() -> from which i am sending my request.
private void foo() {
request.setName1("XYZ");
request.setName2("PQR");
Api.upload(request, new Callback<BasicResponse>() {
#Override
public void onResponse(Call<BasicResponse> call, Response<BasicResponse> response) {
Log.d(TAG, "onResponse: Success" + response.toString());
}
#Override
public void onFailure(Call<BasicResponse> call, Throwable t) {
Log.d(TAG, "onResponse: Failure");
}
});
}
}
my upload Function ->
public static void upload(Request request, Callback<BasicResponse> callback) {
uploadRequest api = retrofit.create(uploadRequest.class);
Call<BasicResponse> call = uploadRequest.uploadCall(POJO);
call.enqueue(callback);
}
This is my UploadRequest Interface ->
public interface uploadRequest{
#POST(UPLOAD_REQUEST)
Call<BasicResponse> uploadCall(#Body POJO pojo);
}
This is My POJO Class
public class POJO {
private String Name1;
private String Name2;
public String getName1() {
return Name1;
}
public void setName1(String name1) {
Name1 = name1;
}
public String getName2() {
return Name2;
}
public void setName2(String name2) {
Name2 = name2;
}
}
And this is my Spring Controller Method
#RequestMapping(value = "/UploadRequest",method = RequestMethod.POST,consumes = "application/json", produces = "application/json")
#ResponseBody
public void UploadImage(#RequestBody POJO pojo,HttpServletRequest request) {
if(pojo!=null){
System.out.println("pojo is not null");
System.out.println(pojo.getName1());
}
else{
System.out.println("null");
}
}
I am getting pojo is not null and inside the pojo.getName1(), the value prints is null.
Edit : Adding BasicResponse Class.
public class BasicResponse {
private boolean success = Boolean.TRUE;
private ErrorCode errorCode;
private String response;
private Integer totalCount;
private String callingUserId;
public BasicResponse() {
super();
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public ErrorCode getErrorCode() {
return errorCode;
}
public void setErrorCode(ErrorCode errorCode) {
this.errorCode = errorCode;
this.success = false;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
public void setResponse(Object response) {
if (response != null) {
this.response = GsonUtils.toGson(response);
}
}
public Integer getTotalCount() {
return totalCount;
}
public void setTotalCount(Integer totalCount) {
this.totalCount = totalCount;
}
public String getCallingUserId() {
return callingUserId;
}
public void setCallingUserId(String callingUserId) {
this.callingUserId = callingUserId;
}
}
Compare the response and your POJO class. The instance variables of your POJO class must be the same as in response. In your case Name1 and Name2. If they are name1, name2 in the response (which means if they do not start with capital letters, etc.), or different, it gives you NullPointerException.
Most likely Name1 and Name2 have different names in json than in your POJO and Jackson, with is used under the hood when you annotate your parameters with #RequestBody can not figure them out, so you get null values. Check out your json.
I am using springboot 2x. Our project is using a Custom HttpServeletRequest which extends HttpServletRequestWrapper and implements MultipartHttpServletRequest. Everything works fine. But when I want to work for file upload, it can't initialized Multipart request. It shows error :
java.lang.IllegalStateException: Multipart request not initialized
My question is, how can I solve this error. How Multipart request will be initialized.
I am giving all code regarding this.
public class XHttpServletRequest extends HttpServletRequestWrapper implements MultipartHttpServletRequest {
public XHttpServletRequest (HttpServletRequest request) {
super(request);
}
private MultiValueMap<String, MultipartFile> multipartFiles;
private String method;
#Override
public String getMethod() {
if (this.method == null) return super.getMethod();
return this.method;
}
public void setMethod(String method) {
this.method = method;
}
private Map<String,String[]> parameters = new LinkedHashMap<String,String[]>();
public void setParameter(String name, String value) {
parameters.put(name, new String[] {value});
}
#Override
public String getParameter(String name) {
if (parameters.get(name) != null) {
return parameters.get(name)[0];
}
HttpServletRequest req = (HttpServletRequest) super.getRequest();
return req.getParameter(name);
}
public Map<String, String[]> getParameterMap() {
Map<String, String[]> result = new LinkedHashMap<String, String[]>();
result.putAll(super.getRequest().getParameterMap());
result.putAll(parameters);
return Collections.<String, String[]>unmodifiableMap(result);
}
public Enumeration<String> getParameterNames() {
Set<String> result = new LinkedHashSet<String>(Collections.list(super.getRequest().getAttributeNames()));
result.addAll(parameters.keySet());
return new Vector<String>(result).elements();
}
public String[] getParameterValues(String name) {
if (parameters.get(name) != null) {
return parameters.get(name);
}
HttpServletRequest req = (HttpServletRequest) super.getRequest();
return req.getParameterValues(name);
}
#Override
public HttpServletRequest getRequest() {
return (HttpServletRequest) super.getRequest();
}
#Override
public HttpMethod getRequestMethod() {
return HttpMethod.resolve(getRequest().getMethod());
}
#Override
public HttpHeaders getRequestHeaders() {
HttpHeaders headers = new HttpHeaders();
Enumeration<String> headerNames = getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
headers.put(headerName, Collections.list(getHeaders(headerName)));
}
return headers;
}
#Override
public HttpHeaders getMultipartHeaders(String s) {
return null;
}
#Override
public Iterator<String> getFileNames() {
return getMultipartFiles().keySet().iterator();
}
#Override
public MultipartFile getFile(String name) {
return getMultipartFiles().getFirst(name);
}
#Override
public List<MultipartFile> getFiles(String name) {
List<MultipartFile> multipartFiles = getMultipartFiles().get(name);
if (multipartFiles != null) {
return multipartFiles;
}
else {
return Collections.emptyList();
}
}
#Override
public Map<String, MultipartFile> getFileMap() {
return getMultipartFiles().toSingleValueMap();
}
#Override
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
return getMultipartFiles();
}
#Override
public String getMultipartContentType(String s) {
return null;
}
/**
* Set a Map with parameter names as keys and list of MultipartFile objects as values.
* To be invoked by subclasses on initialization.
*/
protected final void setMultipartFiles(MultiValueMap<String, MultipartFile> multipartFiles) {
this.multipartFiles =
new LinkedMultiValueMap<>(Collections.unmodifiableMap(multipartFiles));
}
/**
* Obtain the MultipartFile Map for retrieval,
* lazily initializing it if necessary.
* #see #initializeMultipart()
*/
protected MultiValueMap<String, MultipartFile> getMultipartFiles() {
if (this.multipartFiles == null) {
initializeMultipart();
}
return this.multipartFiles;
}
/**
* Lazily initialize the multipart request, if possible.
* Only called if not already eagerly initialized.
*/
protected void initializeMultipart() {
throw new IllegalStateException("Multipart request not initialized");
}
}
Another class extends XHttpServletRequest and this is instead of HttpServeletRequest in our project. The following code:
public class YHttpRequest extends MutableHttpServletRequest {
private ByteArrayOutputStream cachedBytes;
public YHttpRequest(HttpServletRequest request) {
super(request);
}
#Override
public ServletInputStream getInputStream() throws IOException {
if (cachedBytes == null)
cacheInputStream();
return new CachedServletInputStream();
}
#Override
public BufferedReader getReader() throws IOException{
return new BufferedReader(new InputStreamReader(getInputStream()));
}
private void cacheInputStream() throws IOException {
/* Cache the inputstream in order to read it multiple times. For
* convenience, I use apache.commons IOUtils
*/
cachedBytes = new ByteArrayOutputStream();
IOUtils.copy(super.getInputStream(), cachedBytes);
}
public List<Map<String, Object>> getListData() throws RequestException {
List<Map<String, Object>> data = new ArrayList<>();
try {
ObjectMapper mapper = new ObjectMapper();
data = mapper.readValue(this.getInputStream(), new TypeReference<ArrayList<LinkedHashMap>>(){});
System.out.println(data);
}
catch (Exception e) {
// System.out.println(e.)
throw new RequestException("Unable to parse request data", e);
}
return data;
}
private Object cachedData = null;
public Object getRawData() throws RequestException {
Object data = new LinkedHashMap<>();
try {
ObjectMapper mapper = new ObjectMapper();
// data = mapper.readValue(this.getInputStream());
try {
data = mapper.readValue(this.getInputStream(), new TypeReference<HashMap>() {
});
}
catch (JsonMappingException e) {
// e.printStackTrace();
}
try {
data = mapper.readValue(this.getInputStream(), new TypeReference<List<HashMap>>() {
});
}
catch (JsonMappingException e) {
// e.printStackTrace();
}
System.out.println(data);
}
catch (Exception e) {
// System.out.println(e.)
throw new RequestException("Unable to parse request data", e);
}
return data;
}
public Object getData() throws RequestException {
if (this.cachedData == null) {
this.cachedData = this.getRawData();
}
return this.cachedData;
}
/* An inputstream which reads the cached request body */
public class CachedServletInputStream extends ServletInputStream {
private ByteArrayInputStream input;
public CachedServletInputStream() {
/* create a new input stream from the cached request body */
input = new ByteArrayInputStream(cachedBytes.toByteArray());
}
#Override
public boolean isFinished() {
return input.available() == 0;
}
#Override
public boolean isReady() {
return true;
}
#Override
public void setReadListener(ReadListener readListener) {
// throw new IOException("zubair says: Method not implemented in Cached Servlet Input Stream class");
}
#Override
public int read() throws IOException {
return input.read();
}
}
// Storage for Path variable
private Map<String, Object> pathVariableMap = null;
public Map<String, Object> getPathVariableMap() {
if (this.pathVariableMap == null) {
this.pathVariableMap = new LinkedHashMap<>();
this.pathVariableMap.putAll((Map<? extends String, ?>) this.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE));
}
return this.pathVariableMap;
}
public Object getPathVariable(String key) {
return this.getPathVariableMap().get(key);
}
public FurinaHttpRequest setPathVariable(String key, Object value) {
this.getPathVariableMap().put(key, value);
return this;
}
public FurinaHttpRequest clearPathVariableMap() {
this.getPathVariableMap().clear();
return this;
}
}
The controller code:
public String handleFileUpload(YHttpRequest request) {
if (request.getMethod().equalsIgnoreCase("GET")){
return "{}";
}
Map<String, MultipartFile> file= request.getFileMap();
try {
for(Map.Entry<String, MultipartFile> entry : file.entrySet()){
storageService.store(entry.getValue());
//model.addAttribute("message", "You successfully uploaded " + entry.getValue().getOriginalFilename() + "!");
files.add(entry.getValue().getOriginalFilename());
}
} catch (Exception e) {
//model.addAttribute("message", "FAIL to upload !");
}
return "{}";
}
This will work
public String handleFileUpload(YHttpRequest request) {
if (request.getMethod().equalsIgnoreCase("GET")){
return "{}";
}
StandardMultipartHttpServletRequest standardMultipartHttpServletRequest = new StandardMultipartHttpServletRequest(request);
Map<String, MultipartFile> file= request.getFileMap();
try {
for(Map.Entry<String, MultipartFile> entry : file.entrySet()){
storageService.store(entry.getValue());
//model.addAttribute("message", "You successfully uploaded " + entry.getValue().getOriginalFilename() + "!");
files.add(entry.getValue().getOriginalFilename());
}
} catch (Exception e) {
//model.addAttribute("message", "FAIL to upload !");
}
return "{}";
}
This code:
#Override
public List<FactCodeDto> getAllFactsWithoutParentsAsFactDto() {
String completeQuery = FactCodeQueries.SELECT_DTO_FROM_FACT_WITH_NO_PARENTS;
Query query = createHibernateQueryForUnmappedTypeFactDto(completeQuery);
List<FactCodeDto> factDtoList = query.list(); //line 133
return factDtoList;
}
calling this method:
private Query createHibernateQueryForUnmappedTypeFactDto(String sqlQuery) throws HibernateException {
return FactCodeQueries.addScalars(createSQLQuery(sqlQuery)).setResultTransformer(Transformers.aliasToBean(FactCodeDto.class));
}
gives me a ClassCastException -> part of the trace:
Caused by: java.lang.ClassCastException: org.bamboomy.cjr.dto.FactCodeDto cannot be cast to java.util.Map
at org.hibernate.property.access.internal.PropertyAccessMapImpl$SetterImpl.set(PropertyAccessMapImpl.java:102)
at org.hibernate.transform.AliasToBeanResultTransformer.transformTuple(AliasToBeanResultTransformer.java:78)
at org.hibernate.hql.internal.HolderInstantiator.instantiate(HolderInstantiator.java:75)
at org.hibernate.loader.custom.CustomLoader.getResultList(CustomLoader.java:435)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2423)
at org.hibernate.loader.Loader.list(Loader.java:2418)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:336)
at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1898)
at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:318)
at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125)
at org.bamboomy.cjr.dao.factcode.FactCodeDAOImpl.getAllFactsWithoutParentsAsFactDto(FactCodeDAOImpl.java:133)
Which is pretty strange because, indeed, if you look up the source code of Hibernate it tries to do this:
#Override
#SuppressWarnings("unchecked")
public void set(Object target, Object value, SessionFactoryImplementor factory) {
( (Map) target ).put( propertyName, value ); //line 102
}
Which doesn't make any sense...
target is of type Class and this code tries to cast it to Map,
why does it try to do that???
any pointers are more than welcome...
I'm using Hibernate 5 (and am upgrading from 3)...
edit: I also use Spring (4.2.1.RELEASE; also upgrading) which calls these methods upon deploy, any debugging pointers are most welcome as well...
edit 2: (the whole FactCodeDto class, as requested)
package org.bamboomy.cjr.dto;
import org.bamboomy.cjr.model.FactCode;
import org.bamboomy.cjr.model.FactCodeType;
import org.bamboomy.cjr.utility.FullDateUtil;
import org.bamboomy.cjr.utility.Locales;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.util.Assert;
import java.util.*;
#Getter
#Setter
#ToString
public class FactCodeDto extends TreeNodeValue {
private String cdFact;
private String cdFactSuffix;
private Boolean isSupplementCode;
private Boolean isTitleCode;
private Boolean mustBeFollowed;
private Date activeFrom;
private Date activeTo;
private Boolean isCode;
private Long idFact;
private Long idParent;
private String type;
Map<Locale, String> description = new HashMap<Locale, String>(3);
public FactCodeDto() {
}
public FactCodeDto(String prefix, String suffix) {
super();
this.cdFact = prefix;
this.cdFactSuffix = suffix;
}
public FactCodeDto(String cdFact, String cdFactSuffix, Boolean isSupplementCode, Boolean mustBeFollowed) {
super();
this.cdFact = cdFact;
this.cdFactSuffix = cdFactSuffix;
this.isSupplementCode = isSupplementCode;
this.mustBeFollowed = mustBeFollowed;
}
public FactCodeDto(String cdFact, String cdFactSuffix, Boolean isSupplementCode, Boolean mustBeFollowed, Long idFact, Long idParent, Boolean isCode, Boolean isTitleCode, Date from, Date to, Map<Locale, String> descriptions,String type) {
super();
this.cdFact = cdFact;
this.cdFactSuffix = cdFactSuffix;
this.isSupplementCode = isSupplementCode;
this.mustBeFollowed = mustBeFollowed;
this.idFact = idFact;
this.idParent = idParent;
this.isCode = isCode;
this.isTitleCode = isTitleCode;
this.activeFrom = from;
this.activeTo = to;
if (descriptions != null) {
this.description = descriptions;
}
this.type = type;
}
public FactCodeDto(FactCode fc) {
this(fc.getPrefix(), fc.getSuffix(), fc.isSupplementCode(), fc.isHasMandatorySupplCodes(), fc.getId(), fc.getParent(), fc.isActualCode(), fc.isTitleCode(), fc.getActiveFrom(), fc.getActiveTo(), fc.getAllDesc(),fc.getType().getCode());
}
public String formatCode() {
return FactCode.formatCode(cdFact, cdFactSuffix);
}
public boolean isActive() {
Date now = new Date(System.currentTimeMillis());
return FullDateUtil.isBetweenDates(now, this.activeFrom, this.activeTo);
}
public void setDescFr(String s) {
description.put(Locales.FRENCH, s);
}
public void setDescNl(String s) {
description.put(Locales.DUTCH, s);
}
public void setDescDe(String s) {
description.put(Locales.GERMAN, s);
}
/**
* public String toString() {
* StringBuilder sb = new StringBuilder();
* sb.append(getIdFact() + ": ")
* .append(getIdParent() + ": ")
* .append(" " + cdFact + cdFactSuffix + ": " + (isSupplementCode ? "NO Principal " : " Principal "))
* .append((mustBeFollowed ? " Must Be Followed " : "NOT Must Be Followed "));
* return sb.toString();
* }
*/
public Map<Locale, String> getDescription() {
return description;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
String fullCode = formatCode();
result = prime * result + ((fullCode == null) ? 0 : fullCode.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
FactCodeDto other = (FactCodeDto) obj;
return formatCode().equals(other.formatCode());
}
#Override
public boolean isChildOf(TreeNodeValue value) {
Assert.notNull(value);
boolean isChild = false;
if (value instanceof FactCodeDto) {
if (this.getIdParent() != null) {
isChild = this.getIdParent().equals(((FactCodeDto) value).getIdFact());
}
}
return isChild;
}
#Override
public boolean isBrotherOf(TreeNodeValue value) {
Assert.notNull(value);
boolean isBrother = false;
if (value instanceof FactCodeDto) {
if (this.getIdParent() != null) {
isBrother = this.getIdParent().equals(((FactCodeDto) value).getIdParent());
}
}
return isBrother;
}
#Override
public boolean isParentOf(TreeNodeValue value) {
Assert.notNull(value);
boolean isParent = false;
if (value instanceof FactCodeDto) {
isParent = this.getIdFact().equals(((FactCodeDto) value).getIdParent());
}
return isParent;
}
#Override
public int compareTo(TreeNodeValue to) {
if (to instanceof FactCodeDto) {
return formatCode().compareTo(((FactCodeDto) to).formatCode());
} else return 1;
}
public String getCode() {
return formatCode();
}
}
I found that AliasToBean has changed in Hibernate 5. For me adding getter for my field fixed the problem.
This exception occurs when the setters and getters are not mapped correctly to the column names.
Make sure you have the correct getters and setters for the query(Correct names and correct datatypes).
Read more about it here:
http://javahonk.com/java-lang-classcastexception-com-wfs-otc-datamodels-imagineexpirymodel-cannot-cast-java-util-map/
I do some investigation on this question. The problem is that Hibernate converts aliases for column names to upper case — cdFact becomesCDFACT.
Read for a more deeply explanation and workaround here:
mapping Hibernate query results to custom class?
In the end it wasn't so hard to find a solution,
I just created my own (custom) ResultTransformer and specified that in the setResultTransformer method:
private Query createHibernateQueryForUnmappedTypeFactDto(String sqlQuery) throws HibernateException {
return FactCodeQueries.addScalars(createSQLQuery(sqlQuery)).setResultTransformer(new FactCodeDtoResultTransformer());
//return FactCodeQueries.addScalars(createSQLQuery(sqlQuery)).setResultTransformer(Transformers.aliasToBean(FactCodeDto.class));
}
the code of the custom result transformer:
package org.bamboomy.cjr.dao.factcode;
import org.bamboomy.cjr.dto.FactCodeDto;
import java.util.Date;
import java.util.List;
/**
* Created by a162299 on 3-11-2015.
*/
public class FactCodeDtoResultTransformer implements org.hibernate.transform.ResultTransformer {
#Override
public Object transformTuple(Object[] objects, String[] strings) {
FactCodeDto result = new FactCodeDto();
for (int i = 0; i < objects.length; i++) {
setField(result, strings[i], objects[i]);
}
return result;
}
private void setField(FactCodeDto result, String string, Object object) {
if (string.equalsIgnoreCase("cdFact")) {
result.setCdFact((String) object);
} else if (string.equalsIgnoreCase("cdFactSuffix")) {
result.setCdFactSuffix((String) object);
} else if (string.equalsIgnoreCase("isSupplementCode")) {
result.setIsSupplementCode((Boolean) object);
} else if (string.equalsIgnoreCase("isTitleCode")) {
result.setIsTitleCode((Boolean) object);
} else if (string.equalsIgnoreCase("mustBeFollowed")) {
result.setMustBeFollowed((Boolean) object);
} else if (string.equalsIgnoreCase("activeFrom")) {
result.setActiveFrom((Date) object);
} else if (string.equalsIgnoreCase("activeTo")) {
result.setActiveTo((Date) object);
} else if (string.equalsIgnoreCase("descFr")) {
result.setDescFr((String) object);
} else if (string.equalsIgnoreCase("descNl")) {
result.setDescNl((String) object);
} else if (string.equalsIgnoreCase("descDe")) {
result.setDescDe((String) object);
} else if (string.equalsIgnoreCase("type")) {
result.setType((String) object);
} else if (string.equalsIgnoreCase("idFact")) {
result.setIdFact((Long) object);
} else if (string.equalsIgnoreCase("idParent")) {
result.setIdParent((Long) object);
} else if (string.equalsIgnoreCase("isCode")) {
result.setIsCode((Boolean) object);
} else {
throw new RuntimeException("unknown field");
}
}
#Override
public List transformList(List list) {
return list;
}
}
in hibernate 3 you could set Aliasses to queries but you can't do that anymore in hibernate 5 (correct me if I'm wrong) hence the aliasToBean is something you only can use when actually using aliasses; which I didn't, hence the exception.
Im my case :
=> write sql query and try to map result to Class List
=> Use "Transformers.aliasToBean"
=> get Error "cannot be cast to java.util.Map"
Solution :
=> just put \" before and after query aliases
ex:
"select first_name as \"firstName\" from test"
The problem is that Hibernate converts aliases for column names to upper case or lower case
I solved it by defining my own custom transformer as given below -
import org.hibernate.transform.BasicTransformerAdapter;
public class FluentHibernateResultTransformer extends BasicTransformerAdapter {
private static final long serialVersionUID = 6825154815776629666L;
private final Class<?> resultClass;
private NestedSetter[] setters;
public FluentHibernateResultTransformer(Class<?> resultClass) {
this.resultClass = resultClass;
}
#Override
public Object transformTuple(Object[] tuple, String[] aliases) {
createCachedSetters(resultClass, aliases);
Object result = ClassUtils.newInstance(resultClass);
for (int i = 0; i < aliases.length; i++) {
setters[i].set(result, tuple[i]);
}
return result;
}
private void createCachedSetters(Class<?> resultClass, String[] aliases) {
if (setters == null) {
setters = createSetters(resultClass, aliases);
}
}
private static NestedSetter[] createSetters(Class<?> resultClass, String[] aliases) {
NestedSetter[] result = new NestedSetter[aliases.length];
for (int i = 0; i < aliases.length; i++) {
result[i] = NestedSetter.create(resultClass, aliases[i]);
}
return result;
}
}
And used this way inside the repository method -
#Override
public List<WalletVO> getWalletRelatedData(WalletRequest walletRequest,
Set<String> requiredVariablesSet) throws GenericBusinessException {
String query = getWalletQuery(requiredVariablesSet);
try {
if (query != null && !query.isEmpty()) {
SQLQuery sqlQuery = mEntityManager.unwrap(Session.class).createSQLQuery(query);
return sqlQuery.setResultTransformer(new FluentHibernateResultTransformer(WalletVO.class))
.list();
}
} catch (Exception ex) {
exceptionThrower.throwDatabaseException(null, false);
}
return Collections.emptyList();
}
It worked perfectly !!!
Try putting Column names and field names both in capital letters.
This exception occurs when the class that you specified in the AliasToBeanResultTransformer does not have getter for the corresponding columns. Although the exception details from the hibernate are misleading.
I'm modeling a controller reflection based. I would like to know if you agree my implementation and what could to be enhanced.
I'm starting with reflection and I would like to know if I'm using good practices.
Sample: www.sample.com/Main?mvc=user/edit/5
See it:
public class StartController extends HttpServlet {
#Override
public void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String vars = req.getParameter("mvc");
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
MainController main = new MainController();
main.RESTProcess(req, resp, context, vars);
}
}
public class MainController extends Controller {
public void RESTProcess(HttpServletRequest req, HttpServletResponse resp, ApplicationContext context, String vars)
throws IOException, ServletException
{
String[] url;
int nvars;
String controller = null;
String action = null;;
String[] params = null;
int i;
int n;
String controllerName;
String actionName;
if(vars == null || "".equals(vars.trim()))
{
this.redirect(resp,"home");
}
else
{
url = vars.split("/");
nvars = url.length;
if(nvars > 0)
{
controller = url[0].trim(); //users
if(nvars > 1)
{
action = url[1].trim(); //edit
if(nvars > 2)
{
n = 0;
params = new String[nvars - 2]; //array[0] = 5 (iduser)
for(i = 2; i < nvars; i++)
{
params[n] = url[i];
n++;
}
}
}
controllerName = this.getFirstUpper(controller) + "Controller"; //HomeController, UserController pattern
if(!controllerName.equals("Controller"))
{
actionName = "action" + this.getFirstUpper(action); //actionIndex, actionEdit pattern
if(!action.equals("action"))
{
try
{
Class classe = Class.forName("com.sample.controller." + controllerName);
try
{
Constructor c = classe.getConstructor(HttpServletRequest.class, HttpServletResponse.class, String[].class);
try
{
Object obj = c.newInstance(req, resp, context, params);
Method m = classe.getMethod(actionName, null);
m.invoke(obj, null);
System.out.println(obj.toString());
}
catch (Exception e)
{
e.printStackTrace();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
else
{
this.redirect(resp,"home");
}
}
}
public String getFirstUpper(String str)
{
Integer x = str.length();
str = str.substring(0,1).toUpperCase().concat(str.substring(1, x));
return str;
}
}
public class UserController extends Controller {
private HttpServletRequest req;
private HttpServletResponse resp;
private ApplicationContext context;
private String[] params;
public UserController(HttpServletRequest req, HttpServletResponse resp, ApplicationContext context, String[] params)
{
this.req = req;
this.resp = resp;
this.context = context;
this.params = params;
}
public void actionEdit()
{
Long id = Long.valueOf(this.params[0]);
System.out.println("/home/edit");
}
}