@Entity
@Table(name = "COURSE")
public class Course {
@Id
@Column(name = "COURSEID", length = 10)
private String courseID;
@Column(name = "COURSENAME", length = 50)
private String courseName;
@Column(name = "COURSEDESCRIPTION", length = 250)
private String courseDescription;
@OneToMany(mappedBy = "fkCourse", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@MapKey(name = "locale")
private Map<String, CourseLocalized> localizations = new HashMap<>();
public Course() {
}
public Course(String courseID) {
this.courseID = courseID;
}
public String getCourseID() {
return courseID;
}
public void setCourseID(String courseID) {
this.courseID = courseID;
}
public String getCourseName() {
// With fallback language as English
if(localizations.get(LocaleContext.getCurrentLocale()) == null) {
if(localizations.get(LocaleContext.getDefaultLocale()) == null) {
return null;
}
else {
return localizations.get(LocaleContext.getDefaultLocale()).getCourseName();
}
}
return localizations.get(LocaleContext.getCurrentLocale()).getCourseName();
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public String getCourseDescription() {
// With fallback language as English
if(localizations.get(LocaleContext.getCurrentLocale()) == null) {
if(localizations.get(LocaleContext.getDefaultLocale()) == null) {
return null;
}
else {
return localizations.get(LocaleContext.getDefaultLocale()).getCourseDescription();
}
}
return localizations.get(LocaleContext.getCurrentLocale()).getCourseDescription();
}
public void setCourseDescription(String courseDescription) {
this.courseDescription = courseDescription;
}
public Map<String, CourseLocalized> getLocalizations() {
return localizations;
}
public void setLocalizations(Map<String, CourseLocalized> localizations) {
this.localizations = localizations;
}
}
@Entity
@Table(name = "COURSELOCALIZED")
public class CourseLocalized {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID textUUID;
@Column(name = "LOCALE", length = 10)
private String locale;
@Column(name = "COURSENAME", length = 50)
private String courseName;
@Column(name = "COURSEDESCRIPTION", length = 250)
private String courseDescription;
@ManyToOne
@JoinColumn(name = "COURSEID")
private Course fkCourse;
public CourseLocalized() {
}
public CourseLocalized(String locale, String courseName, String courseDescription, Course fkCourse) {
this.locale = locale;
this.courseName = courseName;
this.courseDescription = courseDescription;
this.fkCourse = fkCourse;
}
public CourseLocalized(String locale, Course fkCourse) {
this.locale = locale;
this.fkCourse = fkCourse;
}
// Add getter and setter methods
...
}
public interface CourseRepository extends CrudRepository<Course, String>{
}
@Configuration
public class ODataServletRegistration {
@Bean
ServletRegistrationBean<CXFNonSpringJaxrsServlet> odataBean() {
ServletRegistrationBean<CXFNonSpringJaxrsServlet> odataServlet = new ServletRegistrationBean<CXFNonSpringJaxrsServlet>(new CXFNonSpringJaxrsServlet(),
"/course.srv/*");
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("javax.ws.rs.Application", "org.apache.olingo.odata2.core.rest.app.ODataApplication");
initParameters.put("org.apache.olingo.odata2.service.factory", "com.example.course_localised.config.CustomODataFactory");
odataServlet.setInitParameters(initParameters);
return odataServlet;
}
}
public class CustomODataFactory extends ODataJPAServiceFactory {
public static final String ENTITY_MANAGER_FACTORY_ID = "entityManagerFactory";
private EntityManagerFactory factory;
@Override
public ODataJPAContext initializeODataJPAContext() throws ODataJPARuntimeException {
ODataJPAContext oDataJPAContext = this.getODataJPAContext();
// Here we have considered that only one language will be sent in parameter ACCEPT_LANGUAGE
// But actually there can be multiple languages for example: fr-CH, fr;q=0.9, en;q=0.8
// Here q specifies the weight of acceptable languages. By default the weght is 1.
// i.e. fr-CH has weight 1 and is the most preferred language for the request sent, followed by fr with weight 0.9, followed by en with weight 0.8
// To handle multiple acceptable languages, have a List in LocaleContext and fill the list with acceptable languages
// ODataJPAContext.getODataContext().getAcceptableLanguages() returns the list of acceptable languages in decreasing order of weights
// Setting current language to ACCEPT-LANGUAGE provided in OData request
String locale = oDataJPAContext.getODataContext().getRequestHeader(HttpHeaders.ACCEPT_LANGUAGE);
LocaleContext.setCurrentLocale(locale);
System.out.println("OdataJPAContext started");
try {
factory = (EntityManagerFactory) SpringContextsUtil.getBean(ENTITY_MANAGER_FACTORY_ID);
oDataJPAContext.setEntityManagerFactory(factory);
oDataJPAContext.setPersistenceUnitName("default");
return oDataJPAContext;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public ODataSingleProcessor createCustomODataProcessor(ODataJPAContext oDataJPAContext) {
return new CustomODataJPAProcessor(oDataJPAContext);
}
}
public class CustomODataJPAProcessor extends ODataJPADefaultProcessor {
public static final String ENTITY_MANAGER_FACTORY_ID = "entityManagerFactory";
public static final String COURSE_REPOSITOTY_BEAN_NAME = "courseRepository";
private CourseRepository courseRepository;
private static final String COURSE_ENTITY_SET = "Courses";
public CustomODataJPAProcessor(ODataJPAContext oDataJPAContext) {
super(oDataJPAContext);
}
// Create a new entry in Course entity and save the Course Name and Course Language for the specified language
@Override
public ODataResponse createEntity(PostUriInfo uriInfo, InputStream content, String requestContentType,
String contentType) throws ODataException {
// Get target entity set on which operation is to be performed
String targetEntitySet = uriInfo.getTargetEntitySet().getName();
if (uriInfo.getTargetEntitySet().getEntityType().hasStream()) {
throw new ODataNotImplementedException();
}
// Fetch body from OData request
EntityProviderReadProperties properties = EntityProviderReadProperties.init().mergeSemantic(false).build();
ODataEntry entry = EntityProvider.readEntry(requestContentType, uriInfo.getTargetEntitySet(), content,
properties);
Map<String, Object> data = entry.getProperties();
// Get current language for further processing
String currentLocale = LocaleContext.getCurrentLocale();
if (targetEntitySet.equals(COURSE_ENTITY_SET)) {
System.out.println("In createEntity of " + COURSE_ENTITY_SET);
// Get course repository bean since Autowiring will not work here
// as object of CustomODataJPAProcessor has been created using new operator in createCustomODataProcessor method of CustomODataFactory
courseRepository = (CourseRepository) SpringContextsUtil.getBean(COURSE_REPOSITOTY_BEAN_NAME);
// Get values of properties provided in body
String courseID = (String) data.get("CourseID");
String courseName = (String) data.get("CourseName");
String courseDescription = (String) data.get("CourseDescription");
// Create objects of Course and CourseLocalized and put the CourseLocalized object into localizations map
// And then call save of CourseRepository passing Course object. This would save Course as well as CourseLocalized
Course course = new Course(courseID);
CourseLocalized courseLocalized = new CourseLocalized(currentLocale, courseName, courseDescription, course);
course.getLocalizations().put(currentLocale, courseLocalized);
courseRepository.save(course);
return EntityProvider.writeEntry(contentType, uriInfo.getTargetEntitySet(), entry.getProperties(),
EntityProviderWriteProperties.serviceRoot(getContext().getPathInfo().getServiceRoot()).build());
} else {
return super.createEntity(uriInfo, content, requestContentType, contentType);
}
}
// Saving Course Name and Description in a new language for an existing course will be handled using PUT request i.e. update of course entity
@Override
public ODataResponse updateEntity(PutMergePatchUriInfo uriInfo, InputStream content, String requestContentType,
boolean merge, String contentType) throws ODataException {
// Get target entity set on which operation is to be performed
String targetEntitySet = uriInfo.getTargetEntitySet().getName();
// Fetch body from OData request
EntityProviderReadProperties properties = EntityProviderReadProperties.init().mergeSemantic(false).build();
ODataEntry entry = EntityProvider.readEntry(requestContentType, uriInfo.getTargetEntitySet(), content,
properties);
Map<String, Object> data = entry.getProperties();
// Get current language for further processing
String currentLocale = LocaleContext.getCurrentLocale();
if(targetEntitySet.equals(COURSE_ENTITY_SET)) {
System.out.println("In updateEntity of " + COURSE_ENTITY_SET);
// Get courseID to be processed from key predicates
String courseID = uriInfo.getKeyPredicates().get(0).getLiteral();
// Get course repository bean
courseRepository = (CourseRepository) SpringContextsUtil.getBean(COURSE_REPOSITOTY_BEAN_NAME);
// Get the course object for the courseID passed as key predicate
Optional<Course> courseObj = courseRepository.findById(courseID);
if (courseObj.isPresent()) {
// Get Course from Optional<Course>
Course course = courseObj.get();
CourseLocalized courseLocalized = new CourseLocalized();
if(course.getLocalizations().get(currentLocale) != null) {
courseLocalized = course.getLocalizations().get(currentLocale);
}
else {
courseLocalized.setLocale(currentLocale);
courseLocalized.setFkCourse(course);
}
if (data.get("CourseName") != null) {
String courseName = (String) data.get("CourseName");
courseLocalized.setCourseName(courseName);
}
if(data.get("CourseDescription") != null) {
String courseDescription = (String) data.get("CourseDescription");
courseLocalized.setCourseDescription(courseDescription);
}
course.getLocalizations().put(currentLocale, courseLocalized);
// Save the course object using course repository.
// Both create and update is handled using the save method of repository
courseRepository.save(course);
return ODataResponse.status(HttpStatusCodes.NO_CONTENT).build();
}
else {
// No entry exists for the given courseID
return ODataResponse.status(HttpStatusCodes.NOT_FOUND).build();
}
}
else {
return super.updateEntity(uriInfo, content, requestContentType, merge, contentType);
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
13 | |
11 | |
10 | |
9 | |
9 | |
7 | |
6 | |
5 | |
5 | |
5 |