Common Argument Pass in Method - java

I have a method called makePersistent in my DAO class.
Currntly we have this method in all dao classes and what i need to do is convert this method to common format. So is there any way to do it?
Method in UserDao Class
public void makePersistent(User model) throws InfrastructureException {
try {
getSession().saveOrUpdate(model);
getSession().flush();
getSession().clear();
} catch (org.hibernate.StaleObjectStateException ex) {
throw new InfrastructureException(Labels.getString("com.tran.msg.objectDeletedOrUpdated"));
} catch (HibernateException ex) {
throw new InfrastructureException(ex);
}
}
Method in HolidayDao Class
public void makePersistent(Holiday model) throws InfrastructureException {
try {
getSession().saveOrUpdate(model);
getSession().flush();
getSession().clear();
} catch (org.hibernate.StaleObjectStateException ex) {
throw new InfrastructureException(Labels.getString("com.tran.msg.objectDeletedOrUpdated"));
} catch (HibernateException ex) {
throw new InfrastructureException(ex);
}
}
Please help me to get rid of this redundant coding.
Thank you.

Just use Object the hibernate will persist it.
public void makePersistent(Object model) throws InfrastructureException {
try {
getSession().saveOrUpdate(model);
getSession().flush();
getSession().clear();
} catch (org.hibernate.StaleObjectStateException ex) {
throw new InfrastructureException(Labels.getString("com.tran.msg.objectDeletedOrUpdaed"));
} catch (HibernateException ex) {
throw new InfrastructureException(ex);
}
}

Create a superclass for your DAOs with a type parameter and make your DAO classes extend that superclass with the appropriate type argument. For example:
public class BaseDao<T> {
public void makePersistent(T model) throws InfrastructureException {
try {
getSession().saveOrUpdate(model);
getSession().flush();
getSession().clear();
} catch (org.hibernate.StaleObjectStateException ex) {
throw new InfrastructureException(Labels.getString("com.tran.msg.objectDeletedOrUpdated"));
} catch (HibernateException ex) {
throw new InfrastructureException(ex);
}
}
}
public class UserDao extends BaseDao<User> {
// ...
}
public class HolidayDao extends BaseDao<Holiday> {
// ...
}
UserDao and HolidayDao inherit the makePersistent method from BaseDao, so you don't have to implement it again in every DAO class.

Related

Spring: Generic Resource Controller

I want to create a generic controller that would like something like this:
#RequestMapping("/api/v1/resource/{resource}")
public class StandardController {
private StandardResourceService standardResourceService;
public StandardController(StandardResourceService standardResourceService) {
this.standardResourceService = standardResourceService;
}
#GetMapping("/{id}")
public Object getResource(
#PathVariable(value="resource") String resource,
#PathVariable(value="id") Long id,
HttpServletRequest request){
return standardResourceService.getEntity(id, resource);
}
#PostMapping
#Transactional
Object newResource(#PathVariable(value="resource") String resource, #RequestBody Object newObject) {
standardResourceService.postResource(resource, newObject);
return newObject;
}
}
The idea is that I don't want to have a lot of endpoints/services/controllers for each entity I'll define in the project. I want to create a standard one for each entity and if I need some custom behaviour for some entities, I'll just extend the base service/controller.
The service I've made looks like this:
#Service
public class StandardResourceService {
#Autowired
private EntityManager entityManager;
#Autowired
private ModelMapper modelMapper;
public <T, ID> T findById(Class<T> type, ID id) {
return entityManager.find(type, id);
}
#Transactional
public void saveObject(Object object) {
entityManager.persist(object);
}
public Object getEntity(long resourceId, String resource) throws EntityNotFoundException {
Object resourceOpt;
Object dto;
try{
Class<?> cls = Class.forName("com.base.package.models." + resource);
resourceOpt = findById(cls, resourceId);
}catch (ClassNotFoundException ex){
throw new EntityNotFoundException("Resource " + resource + " could not be found with id: " + resourceId);
}
if(resourceOpt == null) {
throw new EntityNotFoundException("Resource " + resource + " could not be found with id: " + resourceId);
}
try {
Class<?> dtoClass = Class.forName("com.base.package.dto." + resource + "DTO");
dto = modelMapper.map(resourceOpt, dtoClass);
} catch (ClassNotFoundException ex) {
return resourceOpt;
}
return dto;
}
public Object postResource(String resource, Object newObject) throws RuntimeException {
try{
Class<?> clazz = Class.forName("com.base.package.models." + resource);
//saveObject(instance);
}catch (ClassNotFoundException ex){
throw new EntityNotFoundException("");
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return newObject;
}
}
The GET is working pretty good. I return a DTO if any, otherwise I return the entity itself.
By the way when using the POST I don't know how to instantiate the correct class with the body I'm sending in the POST.
Is there a way to do this?
Am I approaching this problem correctly?

how log and rethrow the entire class

I'm using spring.
I have a class with multiple methods. In each method I have to write:
public void method1(){
try{
//anything
}
catch(Exception e){
Log.error(e);
throw e;
}
}
public void method2(){
try{
//anything
}
catch(Exception e){
Log.error(e);
throw e;
}
}
public void method3(){
try{
//anything
}
catch(Exception e){
Log.error(e);
throw e;
}
}
public void method4(){
try{
//anything
}
catch(Exception e){
Log.error(e);
throw e;
}
}
Can I write something to don't have to write this in each method? Maybe an annotation?
Since you are using Spring, #ControllerAdvice would be a nice crispy solution for this case.
All you have to do is do some configuration and define your Global Exception handling class like so
#ControllerAdvice
public class ExceptionControllerAdvice {
// Handles Custom exceptions. MyException in this case
#ExceptionHandler(MyException.class)
public ModelAndView handleMyException(MyException mex) {
ModelAndView model = new ModelAndView();
...
return model;
}
// Handles all the exceptions
#ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception ex) {
ModelAndView model = new ModelAndView();
model.addObject("errMsg", "This is a 'Exception.class' message.");
...
return model;
}
}
Refer to this post for configuring different types of error handling techniques in Spring.
If you just need to rethrow exception there are two solutions:
import lombok.SneakyThrows;
#SneakyThrows //annotation on method of lombok library
import static org.apache.commons.lang3.exception.ExceptionUtils.rethrow;
rethrow() //method from Apache commons library
1)
#SneakyThrows(Exception.class) //without specifying will rethrow all exceptions
public void method1(){
//anything
}
2)
public void method1(){
try{
//anything
}
catch(Exception e){
Log.error(e);
rethrow(e);
}
}

How to regroup catch finally into one method in java 8?

New to java 8, I would like to optimise my code bellow:
public Response create() {
try{
...
} catch (Exception e) {
codeA;
} finally {
codeB;
}
}
public Response update() {
try{
...
} catch (Exception e) {
codeA;
} finally {
codeB;
}
}
I have a lot of methods using this same way to catch exceptions and do the same finally, is that possible to replace the bellow common code by a method in java 8? So that I could optimise all my methods who use this common code.
} catch (Exception e) {
codeA;
} finally {
codeB;
}
Depends what you do in the .... You could do something like this:
private Response method(Supplier<Response> supplier) {
try{
return supplier.get();
} catch (Exception e) {
codeA;
} finally {
codeB;
}
}
and invoke like:
public Response create() { return method(() -> { ... for create }); }
public Response update() { return method(() -> { ... for update }); }
You could wrap your payload and put it to the separate method. One thing; what do you expect to return on exception catch. This time this is null, but probably you could provide default value.
public static <T> T execute(Supplier<T> payload) {
try {
return payload.get();
} catch(Exception e) {
// code A
return null;
} finally {
// code B
}
}
Client code could look like this:
public Response create() {
return execute(() -> new CreateResponse());
}
public Response update() {
return execute(() -> new UpdateResponse());
}
This could be a generic solution.
//here describe supplier which can throw exceptions
#FunctionalInterface
public interface ThrowingSupplier<T> {
T get() throws Exception;
}
// The wrapper
private <T> T callMethod(ThrowingSupplier<T> supplier) {
try {
return supplier.get();
} catch (Exception e) {
//code A
}finally {
// code B
}
}

Catch a exception and show the user a warning about the failed operation

I have a DAO method which catches exceptions in order to perform a rollback of the transaction.
public void edit(Employees em) {
Session s = HibernateUtil.getSessionFactory().getCurrentSession();
try {
s.beginTransaction();
s.update(em);
s.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
s.getTransaction().rollback();
}
}
In the frontend, I'm invoking it as below.
public String save() {
Employee_dao dao = new Employee_dao();
dao.edit(emp);
return "index";
}
However, I would like to catch the exception in the frontend, so I can display a message to the enduser. How can I achieve this while still performing the rollback?
You can simply rethrow the exception, or even wrap it in an exception that contains more information if you need it at the frontend:
public void edit(Employees em) throws Exception {
// ...
try {
s.beginTransaction();
// ...
} catch (Exception e) {
s.getTransaction().rollback();
throw e;
// or throw new MyException("edit failed", e);
// or throw new RuntimeException(...);
}
}
public String save() {
Employee_dao dao = new Employee_dao();
try {
dao.edit(emp);
return "index";
} catch (Exception e) {
return "error";
}
}

How to pass an Object with annotation?

I'm trying to use annotated class as parameters like below:
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface ContextHolder {
}
#ContextHolder
class Foo extends Context {
}
// In some other place
protected Context getContext(ActionHandler handler) {
if (handler.getClass().isAssignableFrom(Context.class)) {
return (Context) handler;
}
for (Method m : handler.getClass().getDeclaredMethods()) {
if (m.getReturnType().isAssignableFrom(Context.class)) {
try {
return (Context) m.invoke(handler);
} catch (IllegalAccessException e) {
ALog.w("", e);
} catch (IllegalArgumentException e) {
ALog.w("", e);
} catch (InvocationTargetException e) {
ALog.w("", e);
}
break;
}
}
ALog.e("Can't find Context in passed ActionHandler");
return null;
}
Foo foo = ...;
getContext(foo?)
The problem is I don't know how to call getContext(). Simply passing foo results compile error.
Any hint will be appreciated. Thanks!

Categories

Resources